Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing...

53
Selenium-Jupiter JUnit 5 extension for Selenium Boni García Version 2.2.0

Transcript of Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing...

Page 1: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Selenium-JupiterJUnit 5 extension for Selenium

Boni Garciacutea

Version 220

Table of ContentsQuick reference 1

Local browsers 3

Chrome 5

Firefox 6

Edge 7

Opera 8

Safari 9

PhamtomJS 10

HtmlUnit 10

Docker browsers 11

Chrome 11

Firefox 13

Opera 14

Android 15

Remote sessions (VNC) 17

Recordings 19

Performance tests 20

Interactive mode 22

Remote browsers 23

Using capabilities 23

Mobile testing with Appium 25

Advanced features 27

Using options 27

Template tests 30

Generic driver 36

Integration with Jenkins 37

Configuration 41

Tuning WebDriverManager 46

Screenshots 47

Known issues 48

Testing localhost 48

Using old versions of Selenium 49

Recordings in Windows or Mac 50

About 51

JUnit 5 is the next generation of the well-known testing framework JUnit Jupiteris the name given to the new programming and extension model provided byJUnit 5 The extension model of JUnit 5 it allows to incorporate extra capabilitiesfor JUnit 5 tests On the other hand Selenium is a testing framework whichallows to control local (Selenium WebDriver) or remote (Selenium Grid) browsers(eg Chrome Firefox and so on) programmatically to carry out automatedtesting of web applications This documentation presents Selenium-Jupiter aJUnit 5 extension aimed to provide seamless integration of Selenium (WebDriverand Grid) for JUnit 5 tests Selenium-Jupiter is open source (Apache 20 license)and is hosted on GitHub

Quick referenceSelenium-Jupiter has been built using the dependency injection capability provided by theextension model of JUnit 5 Thank to this feature different types objects can be injected in JUnit 5 asmethods or constructor parameters in Test classes Concretely Selenium-Jupiter allows to injectsubtypes of the WebDriver interface (eg ChromeDriver FirefoxDriver and so on)

Using Selenium-Jupiter is very easy First you need to import the dependency in your project(typically as test dependency) In Maven it is done as follows

ltdependencygt ltgroupIdgtiogithubbonigarcialtgroupIdgt ltartifactIdgtselenium-jupiterltartifactIdgt ltversiongt220ltversiongt ltscopegttestltscopegtltdependencygt

NOTE

Selenium-Jupiter 220 depends on selenium-java 3130 webdrivermanager 224appium java-client 610 and spotify docker-client 8117 Therefore by using theSelenium-Jupiter dependency these libraries will be added as transitivedependencies to your project

Then you need to declare Selenium-Jupiter extension in your JUnit 5 test simply annotating yourtest with ExtendWith(SeleniumExtensionclass) Finally you need to include one or moreparameters in your Test methods (or constructor) whose types implements the WebDriver interface(eg ChromeDriver to use Chrome FirefoxDriver for Firefox and so for) Thatrsquos it Selenium-Jupitercontrol the lifecycle of the WebDriver object internally and you just need to use the WebDriver objectin your test to drive the browser(s) you want For example

1

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeAndFirefoxJupiterTest

Test public void testWithOneChrome(ChromeDriver chromeDriver) Use Chrome in this test

Test public void testWithFirefox(FirefoxDriver firefoxDriver) Use Firefox in this test

Test public void testWithChromeAndFirefox(ChromeDriver chromeDriver FirefoxDriver firefoxDriver) Use Chrome and Firefox in this test

NOTEAs of JUnit 51 extensions can be registered programmatically viaRegisterExtension or automatically via Javarsquos ServiceLoader Both mechanisms canbe used with Selenium-Jupiter

The WebDriver subtypes supported by Selenium-Jupiter are the following

bull ChromeDriver Used to control Google Chrome browser

bull FirefoxDriver Used to control Firefox browser

bull EdgeDriver Used to control Microsoft Edge browser

bull OperaDriver Used to control Opera browser

bull SafariDriver Used to control Apple Safari browser (only possible in OSX El Capitan or greater)

bull HtmlUnitDriver Used to control HtmlUnit (headless browser)

bull PhantomJSDriver Used to control PhantomJS (headless browser)

bull InternetExplorerDriver Used to control Microsoft Internet Explorer Although this browser issupported Internet Explorer is deprecated (in favor of Edge) and its use is highly discouraged

bull RemoteWebDriver Used to control remote browsers (Selenium Grid)

bull AppiumDriver Used to control mobile devices (Android iOS)

2

WARNING

The browser to be used must be installed in the machine running the testbeforehand (except in the case of RemoteWebDriver in which the requirement isto known a Selenium Server URL) In the case of mobile devices (AppiumDriver)the emulator should be up and running in local or available in a AppiumServer identified by an URL

You can also inject WebDriver objects declaring them as constructor parameters instead of as testmethod parameters For example as follows

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeInConstructorJupiterTest

ChromeDriver driver

public ChromeInConstructorJupiterTest(ChromeDriver driver) thisdriver = driver

Test public void testGlobalChrome() driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This documentation contains a comprehensive collection of basic examples demonstrating thebasic usage of Selenium-Jupiter in JUnit 5 tests using different types of browsers All these examplesare part of the test suite of Selenium-Jupiter and are executed on Travis CI

Local browsersSelenium WebDriver allows to control different types of browsers (such as Chrome Firefox Edgeand so on) programmatically using different programming languages This is very useful toimplement automated tests for web applications Nevertheless in order to use WebDriver we needto pay a prize For security reasons the automated manipulation of a browser can only be doneusing native features of the browser In practical terms it means that a binary file must be placed

3

in between the test using the WebDriver API and the actual browser One the one hand thecommunication between the WebDriver object and that binary is done using the (W3C WebDriverspecification formerly called JSON Wire Protocol It consists basically on a REST service using JSONfor requests and responses On the other hand the communication between the binary and thebrowser is done using native capabilities of the browser Therefore the general schema ofSelenium WebDriver can be illustrated as follows

Figure 1 WebDriver general scenario

From a tester point of view the need of this binary component is a pain in the neck since it shouldbe downloaded manually for the proper platform running the test (ie Windows Linux Mac)Moreover the binary version should be constantly updated The majority of browsers evolve quitefast and the corresponding binary file required by WebDriver needs to be also updated Thefollowing picture shows a fine-grained diagram of the different flavor of WebDriver binaries andbrowsers

Figure 2 WebDriver scenario for Chrome Firefox Opera PhantomJS Edge and Internet Explorer

Concerning Java in order to locate these drivers the absolute path of the binary controlling thebrowser should be exported in a given environment variable before creating a WebDriver instance

4

as follows

SystemsetProperty(webdriverchromedriver pathtochromedriver)SystemsetProperty(webdriveroperadriver pathtooperadriver)SystemsetProperty(webdriveriedriver CpathtoIEDriverServerexe)SystemsetProperty(webdriveredgedriver CpathtoMicrosoftWebDriverexe)SystemsetProperty(phantomjsbinarypath pathtophantomjs)SystemsetProperty(webdrivergeckodriver pathtogeckodriver)

In order to simplify the life of Java WebDriver users in March 2015 the utility WebDriverManagerwas first released WebDriverManager is a library which automates all this process (download theproper binary and export the proper variable) for Java in runtime The WebDriverManager API isquite simple providing a singleton object for each of the above mentioned browsers

WebDriverManagerchromedriver()setup()WebDriverManagerfirefoxdriver()setup()WebDriverManageroperadriver()setup()WebDriverManagerphantomjs()setup()WebDriverManageredgedriver()setup()WebDriverManageriedriver()setup()

The solution implemented by WebDriverManager is today supported by similar tools for otherlanguages such as webdriver-manager for Nodejs or WebDriverManagerNet for NET

On September 2017 a new major version of the well-know testing JUnit framework was releasedThis leads to Selenium-Jupiter which can be seen as the natural evolution of WebDriverManagerfor JUnit 5 tests Internally Selenium-Jupiter is built using two foundations

1 It uses WebDriverManager to manage the binaries requires by WebDriver

2 It uses the dependency injection feature of the extension model of JUnit 5 to inject WebDriverobjects within Test methods

All in all using Selenium WebDriver to control browsers using Java was never that easy Using JUnit5 and Selenium-Jupiter you simply need to declare the flavor of browser you want to use in yourtest method (or constructor) and use it

ChromeThe following example contains a simple usage of Chrome in JUnit 5 The complete source code ofthis test is hosted on GitHub Notice that this class contains two tests (methods annotated withTest) The first one (testWithOneChrome) declares just one ChromeDriver parameter and thereforethis test controls a single Chrome browser On the other hand the second Test (testWithTwoChromes) declares two different ChromeDriver parameters and so it controls two Chromebrowsers

5

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeJupiterTest

Test public void testWithOneChrome(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoChromes(ChromeDriver driver1 ChromeDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

FirefoxThe following test uses Firefox as browser(s) To that aim Test methods simply need to includeFirefoxDriver parameters

6

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxJupiterTest

Test public void testWithOneFirefox(FirefoxDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoFirefoxs(FirefoxDriver driver1 FirefoxDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

EdgeThe following example uses one Edge browser This test should be executed on a Windows machinewith Edge

7

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class EdgeJupiterTest

Test void edgeTest(EdgeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

TIP

The required version of MicrosoftWebDriverexe depends on the version on Edge to beused (more info here) By default WebDriverManager downloads and uses the latestversion of the binaries Nevertheless a concrete version can be fixed Take a look tothe advance examples section to find out how to setup the different options ofWebDriverManager

OperaAre you one of the few using Opera No problem you can still make automated tests with JUnit 5WebDriver and Selenium-Jupiter as follows

8

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumoperaOperaDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class OperaJupiterTest

Test public void test(OperaDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

SafariYou can also use Safari in conjunction with Selenium-Jupiter Take into account that SafariDriverrequires Safari 10 running on OSX El Capitan or greater

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumsafariSafariDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class SafariJupiterTest

Test public void test(SafariDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

9

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 2: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Table of ContentsQuick reference 1

Local browsers 3

Chrome 5

Firefox 6

Edge 7

Opera 8

Safari 9

PhamtomJS 10

HtmlUnit 10

Docker browsers 11

Chrome 11

Firefox 13

Opera 14

Android 15

Remote sessions (VNC) 17

Recordings 19

Performance tests 20

Interactive mode 22

Remote browsers 23

Using capabilities 23

Mobile testing with Appium 25

Advanced features 27

Using options 27

Template tests 30

Generic driver 36

Integration with Jenkins 37

Configuration 41

Tuning WebDriverManager 46

Screenshots 47

Known issues 48

Testing localhost 48

Using old versions of Selenium 49

Recordings in Windows or Mac 50

About 51

JUnit 5 is the next generation of the well-known testing framework JUnit Jupiteris the name given to the new programming and extension model provided byJUnit 5 The extension model of JUnit 5 it allows to incorporate extra capabilitiesfor JUnit 5 tests On the other hand Selenium is a testing framework whichallows to control local (Selenium WebDriver) or remote (Selenium Grid) browsers(eg Chrome Firefox and so on) programmatically to carry out automatedtesting of web applications This documentation presents Selenium-Jupiter aJUnit 5 extension aimed to provide seamless integration of Selenium (WebDriverand Grid) for JUnit 5 tests Selenium-Jupiter is open source (Apache 20 license)and is hosted on GitHub

Quick referenceSelenium-Jupiter has been built using the dependency injection capability provided by theextension model of JUnit 5 Thank to this feature different types objects can be injected in JUnit 5 asmethods or constructor parameters in Test classes Concretely Selenium-Jupiter allows to injectsubtypes of the WebDriver interface (eg ChromeDriver FirefoxDriver and so on)

Using Selenium-Jupiter is very easy First you need to import the dependency in your project(typically as test dependency) In Maven it is done as follows

ltdependencygt ltgroupIdgtiogithubbonigarcialtgroupIdgt ltartifactIdgtselenium-jupiterltartifactIdgt ltversiongt220ltversiongt ltscopegttestltscopegtltdependencygt

NOTE

Selenium-Jupiter 220 depends on selenium-java 3130 webdrivermanager 224appium java-client 610 and spotify docker-client 8117 Therefore by using theSelenium-Jupiter dependency these libraries will be added as transitivedependencies to your project

Then you need to declare Selenium-Jupiter extension in your JUnit 5 test simply annotating yourtest with ExtendWith(SeleniumExtensionclass) Finally you need to include one or moreparameters in your Test methods (or constructor) whose types implements the WebDriver interface(eg ChromeDriver to use Chrome FirefoxDriver for Firefox and so for) Thatrsquos it Selenium-Jupitercontrol the lifecycle of the WebDriver object internally and you just need to use the WebDriver objectin your test to drive the browser(s) you want For example

1

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeAndFirefoxJupiterTest

Test public void testWithOneChrome(ChromeDriver chromeDriver) Use Chrome in this test

Test public void testWithFirefox(FirefoxDriver firefoxDriver) Use Firefox in this test

Test public void testWithChromeAndFirefox(ChromeDriver chromeDriver FirefoxDriver firefoxDriver) Use Chrome and Firefox in this test

NOTEAs of JUnit 51 extensions can be registered programmatically viaRegisterExtension or automatically via Javarsquos ServiceLoader Both mechanisms canbe used with Selenium-Jupiter

The WebDriver subtypes supported by Selenium-Jupiter are the following

bull ChromeDriver Used to control Google Chrome browser

bull FirefoxDriver Used to control Firefox browser

bull EdgeDriver Used to control Microsoft Edge browser

bull OperaDriver Used to control Opera browser

bull SafariDriver Used to control Apple Safari browser (only possible in OSX El Capitan or greater)

bull HtmlUnitDriver Used to control HtmlUnit (headless browser)

bull PhantomJSDriver Used to control PhantomJS (headless browser)

bull InternetExplorerDriver Used to control Microsoft Internet Explorer Although this browser issupported Internet Explorer is deprecated (in favor of Edge) and its use is highly discouraged

bull RemoteWebDriver Used to control remote browsers (Selenium Grid)

bull AppiumDriver Used to control mobile devices (Android iOS)

2

WARNING

The browser to be used must be installed in the machine running the testbeforehand (except in the case of RemoteWebDriver in which the requirement isto known a Selenium Server URL) In the case of mobile devices (AppiumDriver)the emulator should be up and running in local or available in a AppiumServer identified by an URL

You can also inject WebDriver objects declaring them as constructor parameters instead of as testmethod parameters For example as follows

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeInConstructorJupiterTest

ChromeDriver driver

public ChromeInConstructorJupiterTest(ChromeDriver driver) thisdriver = driver

Test public void testGlobalChrome() driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This documentation contains a comprehensive collection of basic examples demonstrating thebasic usage of Selenium-Jupiter in JUnit 5 tests using different types of browsers All these examplesare part of the test suite of Selenium-Jupiter and are executed on Travis CI

Local browsersSelenium WebDriver allows to control different types of browsers (such as Chrome Firefox Edgeand so on) programmatically using different programming languages This is very useful toimplement automated tests for web applications Nevertheless in order to use WebDriver we needto pay a prize For security reasons the automated manipulation of a browser can only be doneusing native features of the browser In practical terms it means that a binary file must be placed

3

in between the test using the WebDriver API and the actual browser One the one hand thecommunication between the WebDriver object and that binary is done using the (W3C WebDriverspecification formerly called JSON Wire Protocol It consists basically on a REST service using JSONfor requests and responses On the other hand the communication between the binary and thebrowser is done using native capabilities of the browser Therefore the general schema ofSelenium WebDriver can be illustrated as follows

Figure 1 WebDriver general scenario

From a tester point of view the need of this binary component is a pain in the neck since it shouldbe downloaded manually for the proper platform running the test (ie Windows Linux Mac)Moreover the binary version should be constantly updated The majority of browsers evolve quitefast and the corresponding binary file required by WebDriver needs to be also updated Thefollowing picture shows a fine-grained diagram of the different flavor of WebDriver binaries andbrowsers

Figure 2 WebDriver scenario for Chrome Firefox Opera PhantomJS Edge and Internet Explorer

Concerning Java in order to locate these drivers the absolute path of the binary controlling thebrowser should be exported in a given environment variable before creating a WebDriver instance

4

as follows

SystemsetProperty(webdriverchromedriver pathtochromedriver)SystemsetProperty(webdriveroperadriver pathtooperadriver)SystemsetProperty(webdriveriedriver CpathtoIEDriverServerexe)SystemsetProperty(webdriveredgedriver CpathtoMicrosoftWebDriverexe)SystemsetProperty(phantomjsbinarypath pathtophantomjs)SystemsetProperty(webdrivergeckodriver pathtogeckodriver)

In order to simplify the life of Java WebDriver users in March 2015 the utility WebDriverManagerwas first released WebDriverManager is a library which automates all this process (download theproper binary and export the proper variable) for Java in runtime The WebDriverManager API isquite simple providing a singleton object for each of the above mentioned browsers

WebDriverManagerchromedriver()setup()WebDriverManagerfirefoxdriver()setup()WebDriverManageroperadriver()setup()WebDriverManagerphantomjs()setup()WebDriverManageredgedriver()setup()WebDriverManageriedriver()setup()

The solution implemented by WebDriverManager is today supported by similar tools for otherlanguages such as webdriver-manager for Nodejs or WebDriverManagerNet for NET

On September 2017 a new major version of the well-know testing JUnit framework was releasedThis leads to Selenium-Jupiter which can be seen as the natural evolution of WebDriverManagerfor JUnit 5 tests Internally Selenium-Jupiter is built using two foundations

1 It uses WebDriverManager to manage the binaries requires by WebDriver

2 It uses the dependency injection feature of the extension model of JUnit 5 to inject WebDriverobjects within Test methods

All in all using Selenium WebDriver to control browsers using Java was never that easy Using JUnit5 and Selenium-Jupiter you simply need to declare the flavor of browser you want to use in yourtest method (or constructor) and use it

ChromeThe following example contains a simple usage of Chrome in JUnit 5 The complete source code ofthis test is hosted on GitHub Notice that this class contains two tests (methods annotated withTest) The first one (testWithOneChrome) declares just one ChromeDriver parameter and thereforethis test controls a single Chrome browser On the other hand the second Test (testWithTwoChromes) declares two different ChromeDriver parameters and so it controls two Chromebrowsers

5

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeJupiterTest

Test public void testWithOneChrome(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoChromes(ChromeDriver driver1 ChromeDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

FirefoxThe following test uses Firefox as browser(s) To that aim Test methods simply need to includeFirefoxDriver parameters

6

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxJupiterTest

Test public void testWithOneFirefox(FirefoxDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoFirefoxs(FirefoxDriver driver1 FirefoxDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

EdgeThe following example uses one Edge browser This test should be executed on a Windows machinewith Edge

7

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class EdgeJupiterTest

Test void edgeTest(EdgeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

TIP

The required version of MicrosoftWebDriverexe depends on the version on Edge to beused (more info here) By default WebDriverManager downloads and uses the latestversion of the binaries Nevertheless a concrete version can be fixed Take a look tothe advance examples section to find out how to setup the different options ofWebDriverManager

OperaAre you one of the few using Opera No problem you can still make automated tests with JUnit 5WebDriver and Selenium-Jupiter as follows

8

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumoperaOperaDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class OperaJupiterTest

Test public void test(OperaDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

SafariYou can also use Safari in conjunction with Selenium-Jupiter Take into account that SafariDriverrequires Safari 10 running on OSX El Capitan or greater

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumsafariSafariDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class SafariJupiterTest

Test public void test(SafariDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

9

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 3: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

JUnit 5 is the next generation of the well-known testing framework JUnit Jupiteris the name given to the new programming and extension model provided byJUnit 5 The extension model of JUnit 5 it allows to incorporate extra capabilitiesfor JUnit 5 tests On the other hand Selenium is a testing framework whichallows to control local (Selenium WebDriver) or remote (Selenium Grid) browsers(eg Chrome Firefox and so on) programmatically to carry out automatedtesting of web applications This documentation presents Selenium-Jupiter aJUnit 5 extension aimed to provide seamless integration of Selenium (WebDriverand Grid) for JUnit 5 tests Selenium-Jupiter is open source (Apache 20 license)and is hosted on GitHub

Quick referenceSelenium-Jupiter has been built using the dependency injection capability provided by theextension model of JUnit 5 Thank to this feature different types objects can be injected in JUnit 5 asmethods or constructor parameters in Test classes Concretely Selenium-Jupiter allows to injectsubtypes of the WebDriver interface (eg ChromeDriver FirefoxDriver and so on)

Using Selenium-Jupiter is very easy First you need to import the dependency in your project(typically as test dependency) In Maven it is done as follows

ltdependencygt ltgroupIdgtiogithubbonigarcialtgroupIdgt ltartifactIdgtselenium-jupiterltartifactIdgt ltversiongt220ltversiongt ltscopegttestltscopegtltdependencygt

NOTE

Selenium-Jupiter 220 depends on selenium-java 3130 webdrivermanager 224appium java-client 610 and spotify docker-client 8117 Therefore by using theSelenium-Jupiter dependency these libraries will be added as transitivedependencies to your project

Then you need to declare Selenium-Jupiter extension in your JUnit 5 test simply annotating yourtest with ExtendWith(SeleniumExtensionclass) Finally you need to include one or moreparameters in your Test methods (or constructor) whose types implements the WebDriver interface(eg ChromeDriver to use Chrome FirefoxDriver for Firefox and so for) Thatrsquos it Selenium-Jupitercontrol the lifecycle of the WebDriver object internally and you just need to use the WebDriver objectin your test to drive the browser(s) you want For example

1

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeAndFirefoxJupiterTest

Test public void testWithOneChrome(ChromeDriver chromeDriver) Use Chrome in this test

Test public void testWithFirefox(FirefoxDriver firefoxDriver) Use Firefox in this test

Test public void testWithChromeAndFirefox(ChromeDriver chromeDriver FirefoxDriver firefoxDriver) Use Chrome and Firefox in this test

NOTEAs of JUnit 51 extensions can be registered programmatically viaRegisterExtension or automatically via Javarsquos ServiceLoader Both mechanisms canbe used with Selenium-Jupiter

The WebDriver subtypes supported by Selenium-Jupiter are the following

bull ChromeDriver Used to control Google Chrome browser

bull FirefoxDriver Used to control Firefox browser

bull EdgeDriver Used to control Microsoft Edge browser

bull OperaDriver Used to control Opera browser

bull SafariDriver Used to control Apple Safari browser (only possible in OSX El Capitan or greater)

bull HtmlUnitDriver Used to control HtmlUnit (headless browser)

bull PhantomJSDriver Used to control PhantomJS (headless browser)

bull InternetExplorerDriver Used to control Microsoft Internet Explorer Although this browser issupported Internet Explorer is deprecated (in favor of Edge) and its use is highly discouraged

bull RemoteWebDriver Used to control remote browsers (Selenium Grid)

bull AppiumDriver Used to control mobile devices (Android iOS)

2

WARNING

The browser to be used must be installed in the machine running the testbeforehand (except in the case of RemoteWebDriver in which the requirement isto known a Selenium Server URL) In the case of mobile devices (AppiumDriver)the emulator should be up and running in local or available in a AppiumServer identified by an URL

You can also inject WebDriver objects declaring them as constructor parameters instead of as testmethod parameters For example as follows

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeInConstructorJupiterTest

ChromeDriver driver

public ChromeInConstructorJupiterTest(ChromeDriver driver) thisdriver = driver

Test public void testGlobalChrome() driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This documentation contains a comprehensive collection of basic examples demonstrating thebasic usage of Selenium-Jupiter in JUnit 5 tests using different types of browsers All these examplesare part of the test suite of Selenium-Jupiter and are executed on Travis CI

Local browsersSelenium WebDriver allows to control different types of browsers (such as Chrome Firefox Edgeand so on) programmatically using different programming languages This is very useful toimplement automated tests for web applications Nevertheless in order to use WebDriver we needto pay a prize For security reasons the automated manipulation of a browser can only be doneusing native features of the browser In practical terms it means that a binary file must be placed

3

in between the test using the WebDriver API and the actual browser One the one hand thecommunication between the WebDriver object and that binary is done using the (W3C WebDriverspecification formerly called JSON Wire Protocol It consists basically on a REST service using JSONfor requests and responses On the other hand the communication between the binary and thebrowser is done using native capabilities of the browser Therefore the general schema ofSelenium WebDriver can be illustrated as follows

Figure 1 WebDriver general scenario

From a tester point of view the need of this binary component is a pain in the neck since it shouldbe downloaded manually for the proper platform running the test (ie Windows Linux Mac)Moreover the binary version should be constantly updated The majority of browsers evolve quitefast and the corresponding binary file required by WebDriver needs to be also updated Thefollowing picture shows a fine-grained diagram of the different flavor of WebDriver binaries andbrowsers

Figure 2 WebDriver scenario for Chrome Firefox Opera PhantomJS Edge and Internet Explorer

Concerning Java in order to locate these drivers the absolute path of the binary controlling thebrowser should be exported in a given environment variable before creating a WebDriver instance

4

as follows

SystemsetProperty(webdriverchromedriver pathtochromedriver)SystemsetProperty(webdriveroperadriver pathtooperadriver)SystemsetProperty(webdriveriedriver CpathtoIEDriverServerexe)SystemsetProperty(webdriveredgedriver CpathtoMicrosoftWebDriverexe)SystemsetProperty(phantomjsbinarypath pathtophantomjs)SystemsetProperty(webdrivergeckodriver pathtogeckodriver)

In order to simplify the life of Java WebDriver users in March 2015 the utility WebDriverManagerwas first released WebDriverManager is a library which automates all this process (download theproper binary and export the proper variable) for Java in runtime The WebDriverManager API isquite simple providing a singleton object for each of the above mentioned browsers

WebDriverManagerchromedriver()setup()WebDriverManagerfirefoxdriver()setup()WebDriverManageroperadriver()setup()WebDriverManagerphantomjs()setup()WebDriverManageredgedriver()setup()WebDriverManageriedriver()setup()

The solution implemented by WebDriverManager is today supported by similar tools for otherlanguages such as webdriver-manager for Nodejs or WebDriverManagerNet for NET

On September 2017 a new major version of the well-know testing JUnit framework was releasedThis leads to Selenium-Jupiter which can be seen as the natural evolution of WebDriverManagerfor JUnit 5 tests Internally Selenium-Jupiter is built using two foundations

1 It uses WebDriverManager to manage the binaries requires by WebDriver

2 It uses the dependency injection feature of the extension model of JUnit 5 to inject WebDriverobjects within Test methods

All in all using Selenium WebDriver to control browsers using Java was never that easy Using JUnit5 and Selenium-Jupiter you simply need to declare the flavor of browser you want to use in yourtest method (or constructor) and use it

ChromeThe following example contains a simple usage of Chrome in JUnit 5 The complete source code ofthis test is hosted on GitHub Notice that this class contains two tests (methods annotated withTest) The first one (testWithOneChrome) declares just one ChromeDriver parameter and thereforethis test controls a single Chrome browser On the other hand the second Test (testWithTwoChromes) declares two different ChromeDriver parameters and so it controls two Chromebrowsers

5

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeJupiterTest

Test public void testWithOneChrome(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoChromes(ChromeDriver driver1 ChromeDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

FirefoxThe following test uses Firefox as browser(s) To that aim Test methods simply need to includeFirefoxDriver parameters

6

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxJupiterTest

Test public void testWithOneFirefox(FirefoxDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoFirefoxs(FirefoxDriver driver1 FirefoxDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

EdgeThe following example uses one Edge browser This test should be executed on a Windows machinewith Edge

7

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class EdgeJupiterTest

Test void edgeTest(EdgeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

TIP

The required version of MicrosoftWebDriverexe depends on the version on Edge to beused (more info here) By default WebDriverManager downloads and uses the latestversion of the binaries Nevertheless a concrete version can be fixed Take a look tothe advance examples section to find out how to setup the different options ofWebDriverManager

OperaAre you one of the few using Opera No problem you can still make automated tests with JUnit 5WebDriver and Selenium-Jupiter as follows

8

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumoperaOperaDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class OperaJupiterTest

Test public void test(OperaDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

SafariYou can also use Safari in conjunction with Selenium-Jupiter Take into account that SafariDriverrequires Safari 10 running on OSX El Capitan or greater

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumsafariSafariDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class SafariJupiterTest

Test public void test(SafariDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

9

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 4: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeAndFirefoxJupiterTest

Test public void testWithOneChrome(ChromeDriver chromeDriver) Use Chrome in this test

Test public void testWithFirefox(FirefoxDriver firefoxDriver) Use Firefox in this test

Test public void testWithChromeAndFirefox(ChromeDriver chromeDriver FirefoxDriver firefoxDriver) Use Chrome and Firefox in this test

NOTEAs of JUnit 51 extensions can be registered programmatically viaRegisterExtension or automatically via Javarsquos ServiceLoader Both mechanisms canbe used with Selenium-Jupiter

The WebDriver subtypes supported by Selenium-Jupiter are the following

bull ChromeDriver Used to control Google Chrome browser

bull FirefoxDriver Used to control Firefox browser

bull EdgeDriver Used to control Microsoft Edge browser

bull OperaDriver Used to control Opera browser

bull SafariDriver Used to control Apple Safari browser (only possible in OSX El Capitan or greater)

bull HtmlUnitDriver Used to control HtmlUnit (headless browser)

bull PhantomJSDriver Used to control PhantomJS (headless browser)

bull InternetExplorerDriver Used to control Microsoft Internet Explorer Although this browser issupported Internet Explorer is deprecated (in favor of Edge) and its use is highly discouraged

bull RemoteWebDriver Used to control remote browsers (Selenium Grid)

bull AppiumDriver Used to control mobile devices (Android iOS)

2

WARNING

The browser to be used must be installed in the machine running the testbeforehand (except in the case of RemoteWebDriver in which the requirement isto known a Selenium Server URL) In the case of mobile devices (AppiumDriver)the emulator should be up and running in local or available in a AppiumServer identified by an URL

You can also inject WebDriver objects declaring them as constructor parameters instead of as testmethod parameters For example as follows

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeInConstructorJupiterTest

ChromeDriver driver

public ChromeInConstructorJupiterTest(ChromeDriver driver) thisdriver = driver

Test public void testGlobalChrome() driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This documentation contains a comprehensive collection of basic examples demonstrating thebasic usage of Selenium-Jupiter in JUnit 5 tests using different types of browsers All these examplesare part of the test suite of Selenium-Jupiter and are executed on Travis CI

Local browsersSelenium WebDriver allows to control different types of browsers (such as Chrome Firefox Edgeand so on) programmatically using different programming languages This is very useful toimplement automated tests for web applications Nevertheless in order to use WebDriver we needto pay a prize For security reasons the automated manipulation of a browser can only be doneusing native features of the browser In practical terms it means that a binary file must be placed

3

in between the test using the WebDriver API and the actual browser One the one hand thecommunication between the WebDriver object and that binary is done using the (W3C WebDriverspecification formerly called JSON Wire Protocol It consists basically on a REST service using JSONfor requests and responses On the other hand the communication between the binary and thebrowser is done using native capabilities of the browser Therefore the general schema ofSelenium WebDriver can be illustrated as follows

Figure 1 WebDriver general scenario

From a tester point of view the need of this binary component is a pain in the neck since it shouldbe downloaded manually for the proper platform running the test (ie Windows Linux Mac)Moreover the binary version should be constantly updated The majority of browsers evolve quitefast and the corresponding binary file required by WebDriver needs to be also updated Thefollowing picture shows a fine-grained diagram of the different flavor of WebDriver binaries andbrowsers

Figure 2 WebDriver scenario for Chrome Firefox Opera PhantomJS Edge and Internet Explorer

Concerning Java in order to locate these drivers the absolute path of the binary controlling thebrowser should be exported in a given environment variable before creating a WebDriver instance

4

as follows

SystemsetProperty(webdriverchromedriver pathtochromedriver)SystemsetProperty(webdriveroperadriver pathtooperadriver)SystemsetProperty(webdriveriedriver CpathtoIEDriverServerexe)SystemsetProperty(webdriveredgedriver CpathtoMicrosoftWebDriverexe)SystemsetProperty(phantomjsbinarypath pathtophantomjs)SystemsetProperty(webdrivergeckodriver pathtogeckodriver)

In order to simplify the life of Java WebDriver users in March 2015 the utility WebDriverManagerwas first released WebDriverManager is a library which automates all this process (download theproper binary and export the proper variable) for Java in runtime The WebDriverManager API isquite simple providing a singleton object for each of the above mentioned browsers

WebDriverManagerchromedriver()setup()WebDriverManagerfirefoxdriver()setup()WebDriverManageroperadriver()setup()WebDriverManagerphantomjs()setup()WebDriverManageredgedriver()setup()WebDriverManageriedriver()setup()

The solution implemented by WebDriverManager is today supported by similar tools for otherlanguages such as webdriver-manager for Nodejs or WebDriverManagerNet for NET

On September 2017 a new major version of the well-know testing JUnit framework was releasedThis leads to Selenium-Jupiter which can be seen as the natural evolution of WebDriverManagerfor JUnit 5 tests Internally Selenium-Jupiter is built using two foundations

1 It uses WebDriverManager to manage the binaries requires by WebDriver

2 It uses the dependency injection feature of the extension model of JUnit 5 to inject WebDriverobjects within Test methods

All in all using Selenium WebDriver to control browsers using Java was never that easy Using JUnit5 and Selenium-Jupiter you simply need to declare the flavor of browser you want to use in yourtest method (or constructor) and use it

ChromeThe following example contains a simple usage of Chrome in JUnit 5 The complete source code ofthis test is hosted on GitHub Notice that this class contains two tests (methods annotated withTest) The first one (testWithOneChrome) declares just one ChromeDriver parameter and thereforethis test controls a single Chrome browser On the other hand the second Test (testWithTwoChromes) declares two different ChromeDriver parameters and so it controls two Chromebrowsers

5

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeJupiterTest

Test public void testWithOneChrome(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoChromes(ChromeDriver driver1 ChromeDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

FirefoxThe following test uses Firefox as browser(s) To that aim Test methods simply need to includeFirefoxDriver parameters

6

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxJupiterTest

Test public void testWithOneFirefox(FirefoxDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoFirefoxs(FirefoxDriver driver1 FirefoxDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

EdgeThe following example uses one Edge browser This test should be executed on a Windows machinewith Edge

7

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class EdgeJupiterTest

Test void edgeTest(EdgeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

TIP

The required version of MicrosoftWebDriverexe depends on the version on Edge to beused (more info here) By default WebDriverManager downloads and uses the latestversion of the binaries Nevertheless a concrete version can be fixed Take a look tothe advance examples section to find out how to setup the different options ofWebDriverManager

OperaAre you one of the few using Opera No problem you can still make automated tests with JUnit 5WebDriver and Selenium-Jupiter as follows

8

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumoperaOperaDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class OperaJupiterTest

Test public void test(OperaDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

SafariYou can also use Safari in conjunction with Selenium-Jupiter Take into account that SafariDriverrequires Safari 10 running on OSX El Capitan or greater

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumsafariSafariDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class SafariJupiterTest

Test public void test(SafariDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

9

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 5: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

WARNING

The browser to be used must be installed in the machine running the testbeforehand (except in the case of RemoteWebDriver in which the requirement isto known a Selenium Server URL) In the case of mobile devices (AppiumDriver)the emulator should be up and running in local or available in a AppiumServer identified by an URL

You can also inject WebDriver objects declaring them as constructor parameters instead of as testmethod parameters For example as follows

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeInConstructorJupiterTest

ChromeDriver driver

public ChromeInConstructorJupiterTest(ChromeDriver driver) thisdriver = driver

Test public void testGlobalChrome() driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This documentation contains a comprehensive collection of basic examples demonstrating thebasic usage of Selenium-Jupiter in JUnit 5 tests using different types of browsers All these examplesare part of the test suite of Selenium-Jupiter and are executed on Travis CI

Local browsersSelenium WebDriver allows to control different types of browsers (such as Chrome Firefox Edgeand so on) programmatically using different programming languages This is very useful toimplement automated tests for web applications Nevertheless in order to use WebDriver we needto pay a prize For security reasons the automated manipulation of a browser can only be doneusing native features of the browser In practical terms it means that a binary file must be placed

3

in between the test using the WebDriver API and the actual browser One the one hand thecommunication between the WebDriver object and that binary is done using the (W3C WebDriverspecification formerly called JSON Wire Protocol It consists basically on a REST service using JSONfor requests and responses On the other hand the communication between the binary and thebrowser is done using native capabilities of the browser Therefore the general schema ofSelenium WebDriver can be illustrated as follows

Figure 1 WebDriver general scenario

From a tester point of view the need of this binary component is a pain in the neck since it shouldbe downloaded manually for the proper platform running the test (ie Windows Linux Mac)Moreover the binary version should be constantly updated The majority of browsers evolve quitefast and the corresponding binary file required by WebDriver needs to be also updated Thefollowing picture shows a fine-grained diagram of the different flavor of WebDriver binaries andbrowsers

Figure 2 WebDriver scenario for Chrome Firefox Opera PhantomJS Edge and Internet Explorer

Concerning Java in order to locate these drivers the absolute path of the binary controlling thebrowser should be exported in a given environment variable before creating a WebDriver instance

4

as follows

SystemsetProperty(webdriverchromedriver pathtochromedriver)SystemsetProperty(webdriveroperadriver pathtooperadriver)SystemsetProperty(webdriveriedriver CpathtoIEDriverServerexe)SystemsetProperty(webdriveredgedriver CpathtoMicrosoftWebDriverexe)SystemsetProperty(phantomjsbinarypath pathtophantomjs)SystemsetProperty(webdrivergeckodriver pathtogeckodriver)

In order to simplify the life of Java WebDriver users in March 2015 the utility WebDriverManagerwas first released WebDriverManager is a library which automates all this process (download theproper binary and export the proper variable) for Java in runtime The WebDriverManager API isquite simple providing a singleton object for each of the above mentioned browsers

WebDriverManagerchromedriver()setup()WebDriverManagerfirefoxdriver()setup()WebDriverManageroperadriver()setup()WebDriverManagerphantomjs()setup()WebDriverManageredgedriver()setup()WebDriverManageriedriver()setup()

The solution implemented by WebDriverManager is today supported by similar tools for otherlanguages such as webdriver-manager for Nodejs or WebDriverManagerNet for NET

On September 2017 a new major version of the well-know testing JUnit framework was releasedThis leads to Selenium-Jupiter which can be seen as the natural evolution of WebDriverManagerfor JUnit 5 tests Internally Selenium-Jupiter is built using two foundations

1 It uses WebDriverManager to manage the binaries requires by WebDriver

2 It uses the dependency injection feature of the extension model of JUnit 5 to inject WebDriverobjects within Test methods

All in all using Selenium WebDriver to control browsers using Java was never that easy Using JUnit5 and Selenium-Jupiter you simply need to declare the flavor of browser you want to use in yourtest method (or constructor) and use it

ChromeThe following example contains a simple usage of Chrome in JUnit 5 The complete source code ofthis test is hosted on GitHub Notice that this class contains two tests (methods annotated withTest) The first one (testWithOneChrome) declares just one ChromeDriver parameter and thereforethis test controls a single Chrome browser On the other hand the second Test (testWithTwoChromes) declares two different ChromeDriver parameters and so it controls two Chromebrowsers

5

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeJupiterTest

Test public void testWithOneChrome(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoChromes(ChromeDriver driver1 ChromeDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

FirefoxThe following test uses Firefox as browser(s) To that aim Test methods simply need to includeFirefoxDriver parameters

6

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxJupiterTest

Test public void testWithOneFirefox(FirefoxDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoFirefoxs(FirefoxDriver driver1 FirefoxDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

EdgeThe following example uses one Edge browser This test should be executed on a Windows machinewith Edge

7

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class EdgeJupiterTest

Test void edgeTest(EdgeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

TIP

The required version of MicrosoftWebDriverexe depends on the version on Edge to beused (more info here) By default WebDriverManager downloads and uses the latestversion of the binaries Nevertheless a concrete version can be fixed Take a look tothe advance examples section to find out how to setup the different options ofWebDriverManager

OperaAre you one of the few using Opera No problem you can still make automated tests with JUnit 5WebDriver and Selenium-Jupiter as follows

8

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumoperaOperaDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class OperaJupiterTest

Test public void test(OperaDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

SafariYou can also use Safari in conjunction with Selenium-Jupiter Take into account that SafariDriverrequires Safari 10 running on OSX El Capitan or greater

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumsafariSafariDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class SafariJupiterTest

Test public void test(SafariDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

9

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 6: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

in between the test using the WebDriver API and the actual browser One the one hand thecommunication between the WebDriver object and that binary is done using the (W3C WebDriverspecification formerly called JSON Wire Protocol It consists basically on a REST service using JSONfor requests and responses On the other hand the communication between the binary and thebrowser is done using native capabilities of the browser Therefore the general schema ofSelenium WebDriver can be illustrated as follows

Figure 1 WebDriver general scenario

From a tester point of view the need of this binary component is a pain in the neck since it shouldbe downloaded manually for the proper platform running the test (ie Windows Linux Mac)Moreover the binary version should be constantly updated The majority of browsers evolve quitefast and the corresponding binary file required by WebDriver needs to be also updated Thefollowing picture shows a fine-grained diagram of the different flavor of WebDriver binaries andbrowsers

Figure 2 WebDriver scenario for Chrome Firefox Opera PhantomJS Edge and Internet Explorer

Concerning Java in order to locate these drivers the absolute path of the binary controlling thebrowser should be exported in a given environment variable before creating a WebDriver instance

4

as follows

SystemsetProperty(webdriverchromedriver pathtochromedriver)SystemsetProperty(webdriveroperadriver pathtooperadriver)SystemsetProperty(webdriveriedriver CpathtoIEDriverServerexe)SystemsetProperty(webdriveredgedriver CpathtoMicrosoftWebDriverexe)SystemsetProperty(phantomjsbinarypath pathtophantomjs)SystemsetProperty(webdrivergeckodriver pathtogeckodriver)

In order to simplify the life of Java WebDriver users in March 2015 the utility WebDriverManagerwas first released WebDriverManager is a library which automates all this process (download theproper binary and export the proper variable) for Java in runtime The WebDriverManager API isquite simple providing a singleton object for each of the above mentioned browsers

WebDriverManagerchromedriver()setup()WebDriverManagerfirefoxdriver()setup()WebDriverManageroperadriver()setup()WebDriverManagerphantomjs()setup()WebDriverManageredgedriver()setup()WebDriverManageriedriver()setup()

The solution implemented by WebDriverManager is today supported by similar tools for otherlanguages such as webdriver-manager for Nodejs or WebDriverManagerNet for NET

On September 2017 a new major version of the well-know testing JUnit framework was releasedThis leads to Selenium-Jupiter which can be seen as the natural evolution of WebDriverManagerfor JUnit 5 tests Internally Selenium-Jupiter is built using two foundations

1 It uses WebDriverManager to manage the binaries requires by WebDriver

2 It uses the dependency injection feature of the extension model of JUnit 5 to inject WebDriverobjects within Test methods

All in all using Selenium WebDriver to control browsers using Java was never that easy Using JUnit5 and Selenium-Jupiter you simply need to declare the flavor of browser you want to use in yourtest method (or constructor) and use it

ChromeThe following example contains a simple usage of Chrome in JUnit 5 The complete source code ofthis test is hosted on GitHub Notice that this class contains two tests (methods annotated withTest) The first one (testWithOneChrome) declares just one ChromeDriver parameter and thereforethis test controls a single Chrome browser On the other hand the second Test (testWithTwoChromes) declares two different ChromeDriver parameters and so it controls two Chromebrowsers

5

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeJupiterTest

Test public void testWithOneChrome(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoChromes(ChromeDriver driver1 ChromeDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

FirefoxThe following test uses Firefox as browser(s) To that aim Test methods simply need to includeFirefoxDriver parameters

6

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxJupiterTest

Test public void testWithOneFirefox(FirefoxDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoFirefoxs(FirefoxDriver driver1 FirefoxDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

EdgeThe following example uses one Edge browser This test should be executed on a Windows machinewith Edge

7

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class EdgeJupiterTest

Test void edgeTest(EdgeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

TIP

The required version of MicrosoftWebDriverexe depends on the version on Edge to beused (more info here) By default WebDriverManager downloads and uses the latestversion of the binaries Nevertheless a concrete version can be fixed Take a look tothe advance examples section to find out how to setup the different options ofWebDriverManager

OperaAre you one of the few using Opera No problem you can still make automated tests with JUnit 5WebDriver and Selenium-Jupiter as follows

8

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumoperaOperaDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class OperaJupiterTest

Test public void test(OperaDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

SafariYou can also use Safari in conjunction with Selenium-Jupiter Take into account that SafariDriverrequires Safari 10 running on OSX El Capitan or greater

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumsafariSafariDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class SafariJupiterTest

Test public void test(SafariDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

9

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 7: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

as follows

SystemsetProperty(webdriverchromedriver pathtochromedriver)SystemsetProperty(webdriveroperadriver pathtooperadriver)SystemsetProperty(webdriveriedriver CpathtoIEDriverServerexe)SystemsetProperty(webdriveredgedriver CpathtoMicrosoftWebDriverexe)SystemsetProperty(phantomjsbinarypath pathtophantomjs)SystemsetProperty(webdrivergeckodriver pathtogeckodriver)

In order to simplify the life of Java WebDriver users in March 2015 the utility WebDriverManagerwas first released WebDriverManager is a library which automates all this process (download theproper binary and export the proper variable) for Java in runtime The WebDriverManager API isquite simple providing a singleton object for each of the above mentioned browsers

WebDriverManagerchromedriver()setup()WebDriverManagerfirefoxdriver()setup()WebDriverManageroperadriver()setup()WebDriverManagerphantomjs()setup()WebDriverManageredgedriver()setup()WebDriverManageriedriver()setup()

The solution implemented by WebDriverManager is today supported by similar tools for otherlanguages such as webdriver-manager for Nodejs or WebDriverManagerNet for NET

On September 2017 a new major version of the well-know testing JUnit framework was releasedThis leads to Selenium-Jupiter which can be seen as the natural evolution of WebDriverManagerfor JUnit 5 tests Internally Selenium-Jupiter is built using two foundations

1 It uses WebDriverManager to manage the binaries requires by WebDriver

2 It uses the dependency injection feature of the extension model of JUnit 5 to inject WebDriverobjects within Test methods

All in all using Selenium WebDriver to control browsers using Java was never that easy Using JUnit5 and Selenium-Jupiter you simply need to declare the flavor of browser you want to use in yourtest method (or constructor) and use it

ChromeThe following example contains a simple usage of Chrome in JUnit 5 The complete source code ofthis test is hosted on GitHub Notice that this class contains two tests (methods annotated withTest) The first one (testWithOneChrome) declares just one ChromeDriver parameter and thereforethis test controls a single Chrome browser On the other hand the second Test (testWithTwoChromes) declares two different ChromeDriver parameters and so it controls two Chromebrowsers

5

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeJupiterTest

Test public void testWithOneChrome(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoChromes(ChromeDriver driver1 ChromeDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

FirefoxThe following test uses Firefox as browser(s) To that aim Test methods simply need to includeFirefoxDriver parameters

6

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxJupiterTest

Test public void testWithOneFirefox(FirefoxDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoFirefoxs(FirefoxDriver driver1 FirefoxDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

EdgeThe following example uses one Edge browser This test should be executed on a Windows machinewith Edge

7

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class EdgeJupiterTest

Test void edgeTest(EdgeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

TIP

The required version of MicrosoftWebDriverexe depends on the version on Edge to beused (more info here) By default WebDriverManager downloads and uses the latestversion of the binaries Nevertheless a concrete version can be fixed Take a look tothe advance examples section to find out how to setup the different options ofWebDriverManager

OperaAre you one of the few using Opera No problem you can still make automated tests with JUnit 5WebDriver and Selenium-Jupiter as follows

8

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumoperaOperaDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class OperaJupiterTest

Test public void test(OperaDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

SafariYou can also use Safari in conjunction with Selenium-Jupiter Take into account that SafariDriverrequires Safari 10 running on OSX El Capitan or greater

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumsafariSafariDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class SafariJupiterTest

Test public void test(SafariDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

9

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 8: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeJupiterTest

Test public void testWithOneChrome(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoChromes(ChromeDriver driver1 ChromeDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

FirefoxThe following test uses Firefox as browser(s) To that aim Test methods simply need to includeFirefoxDriver parameters

6

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxJupiterTest

Test public void testWithOneFirefox(FirefoxDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoFirefoxs(FirefoxDriver driver1 FirefoxDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

EdgeThe following example uses one Edge browser This test should be executed on a Windows machinewith Edge

7

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class EdgeJupiterTest

Test void edgeTest(EdgeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

TIP

The required version of MicrosoftWebDriverexe depends on the version on Edge to beused (more info here) By default WebDriverManager downloads and uses the latestversion of the binaries Nevertheless a concrete version can be fixed Take a look tothe advance examples section to find out how to setup the different options ofWebDriverManager

OperaAre you one of the few using Opera No problem you can still make automated tests with JUnit 5WebDriver and Selenium-Jupiter as follows

8

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumoperaOperaDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class OperaJupiterTest

Test public void test(OperaDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

SafariYou can also use Safari in conjunction with Selenium-Jupiter Take into account that SafariDriverrequires Safari 10 running on OSX El Capitan or greater

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumsafariSafariDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class SafariJupiterTest

Test public void test(SafariDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

9

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 9: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestCoreMatchersstartsWithimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumfirefoxFirefoxDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxJupiterTest

Test public void testWithOneFirefox(FirefoxDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testWithTwoFirefoxs(FirefoxDriver driver1 FirefoxDriver driver2) driver1get(httpwwwseleniumhqorg) driver2get(httpjunitorgjunit5) assertThat(driver1getTitle() startsWith(Selenium)) assertThat(driver2getTitle() equalTo(JUnit 5))

EdgeThe following example uses one Edge browser This test should be executed on a Windows machinewith Edge

7

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class EdgeJupiterTest

Test void edgeTest(EdgeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

TIP

The required version of MicrosoftWebDriverexe depends on the version on Edge to beused (more info here) By default WebDriverManager downloads and uses the latestversion of the binaries Nevertheless a concrete version can be fixed Take a look tothe advance examples section to find out how to setup the different options ofWebDriverManager

OperaAre you one of the few using Opera No problem you can still make automated tests with JUnit 5WebDriver and Selenium-Jupiter as follows

8

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumoperaOperaDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class OperaJupiterTest

Test public void test(OperaDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

SafariYou can also use Safari in conjunction with Selenium-Jupiter Take into account that SafariDriverrequires Safari 10 running on OSX El Capitan or greater

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumsafariSafariDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class SafariJupiterTest

Test public void test(SafariDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

9

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 10: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class EdgeJupiterTest

Test void edgeTest(EdgeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

TIP

The required version of MicrosoftWebDriverexe depends on the version on Edge to beused (more info here) By default WebDriverManager downloads and uses the latestversion of the binaries Nevertheless a concrete version can be fixed Take a look tothe advance examples section to find out how to setup the different options ofWebDriverManager

OperaAre you one of the few using Opera No problem you can still make automated tests with JUnit 5WebDriver and Selenium-Jupiter as follows

8

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumoperaOperaDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class OperaJupiterTest

Test public void test(OperaDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

SafariYou can also use Safari in conjunction with Selenium-Jupiter Take into account that SafariDriverrequires Safari 10 running on OSX El Capitan or greater

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumsafariSafariDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class SafariJupiterTest

Test public void test(SafariDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

9

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 11: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumoperaOperaDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class OperaJupiterTest

Test public void test(OperaDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

SafariYou can also use Safari in conjunction with Selenium-Jupiter Take into account that SafariDriverrequires Safari 10 running on OSX El Capitan or greater

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumsafariSafariDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class SafariJupiterTest

Test public void test(SafariDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

9

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 12: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

PhamtomJSPhamtomJS is a headless browser (ie a browser without GUI) and it can be convenient fordifferent types of tests The following example demonstrates how to use PhamtomJS with Selenium-Jupiter

import static orghamcrestCoreMatchersnotNullValueimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumphantomjsPhantomJSDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PhantomjsJupiterTest

Test public void test(PhantomJSDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetPageSource() notNullValue())

HtmlUnitHtmlUnit is another headless browser that can be used easily in a Jupiter test for example like this

10

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 13: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumhtmlunitHtmlUnitDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class HtmlUnitJupiterTest

Test public void test(HtmlUnitDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Docker browsersAs of version 200 Selenium-Jupiter allows to ask for browsers in Docker containers The onlyrequirement to use this feature is to install Docker Engine in the machine running the testsInternally Selenium-Jupiter uses a docker-client and different Docker images for browsers namely

bull Stable versions of Docker browser provided by Selenoid

bull Beta and nightly versions of Docker browser provided by ElasTest

bull Browsers in Android devices provided by Budi Utomo

As shown in the following section the mode of operation is similar to local browser We simply asksfor browsers in Docker simply declaring parameters in our Test methods and Selenium-Jupiterwill make magic for us it downloads the proper Docker image for the browser start it andinstantiate the object of type WebDriver or RemoteWebDriver to control the browser from our test Theannotation DockerBrowser need to be declared in the parameter to mark the WebDriver object as abrowser in Docker

ChromeThe following example contains a simple test example using Chrome browsers in Docker Check outthe code here As you can see the first Test method (called testChrome) declares a parameter oftype RemoteWebDriver This parameter is annotated with DockerBrowser This annotation requires toset the browser type in this case CHROME If no version is specified then the latest version of thebrowser will be used This feature is known as evergreen Docker browsers and it is implementingby consuming the REST API of Docker Hub asking for the list of Selenoid browsers On the other

11

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 14: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

hand the second Test (called testChromeWithVersion) a fixed version is set in this case 670

import static iogithubbonigarciaBrowserTypeCHROMEimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeJupiterTest

Test public void testChrome( DockerBrowser(type = CHROME) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testChromeWithVersion( DockerBrowser(type = CHROME version = 670) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

In this other example wildcards are used to set the browser version In the first Test (methodtestLatestChrome) we use the literal latest to mark the use of the latest version (in fact the use oflatest is exactly the same that not declaring the version attribute) The second Test (methodtestFormerChrome) sets the version as latest-1 This should be read as latest version minus one inother words the previous version to the stable version at the time of the test execution Notice thatthe concrete versions for both test will evolve in time since new versions are released constantlyAll in all you have the certainty of using the latest versions of the browser without any kind ofextra configuration nor maintenance of the underlying infrastructure

Moreover in third (testBetaChrome) and fourth (testUnstableChrome) test beta and unstable (iedevelopment) versions are used This feature is available both for Chrome and Firefox thanks tothe Docker images provided by the ElasTest project

12

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 15: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static iogithubbonigarciaBrowserTypeCHROME

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerChromeLatestJupiterTest

Test public void testLatestChrome( DockerBrowser(type = CHROME version = latest) WebDriver driver) Use stable version of Chrome in this test

Test public void testFormerChrome( DockerBrowser(type = CHROME version = latest-1) WebDriver driver) Use previous to stable version of Chrome in this test

Test public void testBetaChrome( DockerBrowser(type = CHROME version = beta) WebDriver driver) Use beta version of Chrome in this test

Test public void testUnstableChrome( DockerBrowser(type = CHROME version = unstable) WebDriver driver) Use development version of Chrome in this test

NOTE

The label latest- is supported where is a number for a former version to thecurrent stable For instance latest-2 means the two previous version to the stable(for instance if at the time of running a test the latest version is 630 latest-2 willmean version 610)

FirefoxThe use of Firefox is equivalent With respect to the previous example it simply change the type ofbrowser Versioning works exactly the same

13

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 16: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static iogithubbonigarciaBrowserTypeFIREFOXimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerFirefoxJupiterTest

Test public void testLatest( DockerBrowser(type = FIREFOX) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test public void testVersion( DockerBrowser(type = FIREFOX version = 60) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

NOTENotice that the version of the second test is simply 60 The actual version of theimage is 600 but Selenium-Jupiter supposes that version is 0 if not specified

OperaAgain the use of Opera browsers in Docker is the same simply changing the browser type to OPERA

14

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 17: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static iogithubbonigarciaBrowserTypeOPERAimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerOperaJupiterTest

Test public void testOpera(DockerBrowser(type = OPERA) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

AndroidThe use of browser devices in Selenium-Jupiter is straightforward Simply change the browser typeto ANDROID as follows

15

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 18: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidJupiterTest

Test public void testAndroid( DockerBrowser(type = ANDROID) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The supported Android devices are summarized in the following table

Table 1 Android devices in Selenium-Jupiter

Android version API level Browser name

501 21 browser

511 22 browser

60 23 chrome

70 24 chrome

711 25 chrome

Moreover the type of devices are the following

Table 2 Android devices types in Selenium-Jupiter

Type Device name

Phone Samsung Galaxy S6

Phone Nexus 4

Phone Nexus 5

Phone Nexus One

Phone Nexus S

16

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 19: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Type Device name

Tablet Nexus 7

By default the latest version of Android (711) using Chrome in a Samsung Galaxy S6 These valuescan be changed using the configuration capabilities or by means of the the following parameters inthe DockerBrowser annotation

import static iogithubbonigarciaBrowserTypeANDROIDimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class DockerAndroidCustomJupiterTest

Test public void testAndroid(DockerBrowser(type = ANDROID version = 501 deviceName = Nexus S browserName = browser) RemoteWebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Remote sessions (VNC)Selenium-Jupiter allows to track the evolution of our browsers in Docker using Virtual NetworkComputing (VNC) sessions This feature is disabled by default but it can activated using theconfiguration key seljupvnc to true (more info on section Configuration)

When it is activated the VNC URL of a browser in Docker is printed in the test log concretely usingthe DEBUG level (see example below) Simply copying and pasting that URL in a real browser wecan take a look to the browser while the test is being executed We can even interact with theDocker browser

2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler - VNC URL (copy andpaste in a browser navigation bar to interact with remote session)2018-03-31 170703 [main] INFO igbhandlerDockerDriverHandler -http1921689910032769vnchtmlhost=19216899100ampport=32768amppath=vncaa39e2562bf0f58bfbad0924d22ca958ampresize=scaleampautoconnect=trueamppassword=selenoid

17

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 20: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Figure 3 Example of VNC session of Chrome (desktop)

18

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 21: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Figure 4 Example of VNC session of Chrome (Android)

NOTEIn addition to log the VNC URL as of Selenium-Jupiter 210 the value of this URL isexported as Java property as vncsessionurl (ieSystemsetProperty(vncsessionurl vncUrl))

RecordingsSelenium-Jupiter allows to record the sessions of browsers in Docker This capability is not activatedby default but it activated simply setting the configuration key seljuprecording to true (seesection Configuration for further details about configuration)

This way a recording in MP4 format will be stored at the end of the test which uses one or severalbrowsers in Docker The output folder in which the recording is stored is configured by means ofthe configuration key seljupoutputfolder whose default value is (ie the current folder inwhich the test is executed) The following picture shows an example of recording

19

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 22: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Figure 5 Example of recording played in VLC

Performance testsAnother important new feature of browsers in Docker is the possibility of asking for many of themby the same test This can be used to implement performance tests in a seamless way To use thisfeature we need into account two aspects First of all the attribute size of the annotationDockerBrowser should be declared This numeric value sets the number of browsers demanded bythe test Second the test declares a ListltRemoteWebDrivergt (or ListltWebDrivergt) For example asfollows

import static iogithubbonigarciaBrowserTypeCHROMEimport static javalanginvokeMethodHandleslookupimport static javautilconcurrentExecutorsnewFixedThreadPoolimport static javautilconcurrentTimeUnitSECONDSimport static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgslf4jLoggerFactorygetLogger

import javautilList

20

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 23: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import javautilconcurrentCountDownLatchimport javautilconcurrentExecutorService

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumremoteRemoteWebDriverimport orgslf4jLogger

import iogithubbonigarciaDockerBrowserimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class PerformenceDockerChromeJupiterTest

static final int NUM_BROWSERS = 3

final Logger log = getLogger(lookup()lookupClass())

Test public void testPerformance( DockerBrowser(type = CHROME version = 670 size = NUM_BROWSERS) ListltRemoteWebDrivergt driverList) throws InterruptedException

ExecutorService executorService = newFixedThreadPool(NUM_BROWSERS) CountDownLatch latch = new CountDownLatch(NUM_BROWSERS)

driverListforEach((driver) -gt executorServicesubmit(() -gt try loginfo(Session id ((RemoteWebDriver) driver)getSessionId()) driverget( httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString( JUnit 5 extension for Selenium)) finally latchcountDown() ) )

latchawait(50 SECONDS) executorServiceshutdown()

This example requires a list of 3 Chrome browsers in Docker Then it executed in parallel a givenlogic Notice that if the number of browsers is high the CPU and memory consumption of the test

21

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 24: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

running the machine will increase accordingly

Interactive modeAs of version 210 Selenium-Jupiter can used interactively from the shell to get the VNC session ofDocker browser There are two ways of using this feature

bull Directly from the source code using Maven The command to be used is mvn execjava

-Dexecargs=browserName ltversiongt For instance

$ mvn execjava -Dexecargs=chrome beta[INFO] Scanning for projects[INFO][INFO] ------------------------------------------------------------------------[INFO] Building selenium-jupiter 212-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO][INFO] --- exec-maven-plugin160java (default-cli) selenium-jupiter ---[INFO] Using SeleniumJupiter to execute chrome beta in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using CHROME version beta[INFO] Pulling Docker image elastestbrowserschromebeta please wait[INFO] Starting Docker container aerokubeselenoid160mar 31 2018 55015 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect OSS[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 957187e9f3f99312ebd2c81546750643[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032775vnchtmlhost=19216899100ampport=32774amppath=vnc957187e9f3f99312ebd2c81546750643ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container aerokubeselenoid160[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time 0110 min[INFO] Finished at 2018-03-31T175115+0200[INFO] Final Memory 27M390M[INFO] ------------------------------------------------------------------------

bull Using Selenium-Jupiter as a fat-jar This jar can be created using the command mvn compileassemblysingle from the source code and then java -jar selenium-jupiterjar browserNameltversiongt For instance

22

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 25: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

$ java -jar selenium-jupiter-212-SNAPSHOT-jar-with-dependenciesjar firefox[INFO] Using SeleniumJupiter to execute firefox (latest) in Docker[INFO] Getting browser image list from Docker Hub[INFO] Using FIREFOX version 590 (latest)[INFO] Pulling Docker image selenoidvncfirefox_590 please wait[INFO] Starting Docker container aerokubeselenoid163mar 31 2018 55351 PM orgopenqaseleniumremoteProtocolHandshake createSessionINFORMATION Detected dialect W3C[INFO] Starting Docker container psharkeynovnc33-t6[INFO] Session id 651fcf54-183e-4732-8fae-6a525140f6f0[INFO] VNC URL (copy and paste in a browser navigation bar to interact with remotesession)[INFO]http1921689910032777vnchtmlhost=19216899100ampport=32776amppath=vnc651fcf54-183e-4732-8fae-6a525140f6f0ampresize=scaleampautoconnect=trueamppassword=selenoid[INFO] Press ENTER to exit

[INFO] Stopping Docker container psharkeynovnc33-t6[INFO] Stopping Docker container aerokubeselenoid163

NOTE

As of version 220 the parameter browserName can be used to select an androiddevice In this case a couple of addition parameter can be specifiedbrowserNameInAdroid for the browser in Android (chrome or browser) and deviceNamefor the device type (Samsung Galaxy S6 Nexus 4 Nexus 5 etc)

Remote browsersSelenium-Jupiter also supports remote browsers using a Selenium Grid server To that aim a coupleof custom annotations can be used

bull DriverUrl (parameter-level or field-level) Annotation used to identify the URL value needed toinstantiate a RemoteWebDriver object This URL can be setup using the configuration keyseljupseleniumserverurl This value can be used to use browsers from cloud providers suchas Saucelabs or BrowserStack

bull DriverCapabilities (parameter-level or field-level) Annotation to configure the desiredcapabilities (WebDriverrsquos object DesiredCapabilities)

Using capabilitiesThe annotation DriverCapabilities is used to specify WebDriver capabilities (ie type browserversion platform etc) These capabilities are typically used for Selenium Grid tets (ie tests usingremote browsers) To that aim an Selenium Hub (also known as Selenium Server) should be up anrunning and its URL should known This URL will be specified using the Selenium-Jupiterannotation DriverUrl

The following example provides a complete example about this As you can see in the test setup

23

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 26: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

(BeforeAll) a Selenium Grid is implemented first starting a Hub (aka Selenium Server) and thena couple of nodes (Chrome a Firefox) are registered in the Hub Therefore remote test usingRemoteWebDriver can be executed simply pointing to the Hub (whose URL in this case ishttplocalhost4444wdhub in this example) and selecting the browser to be used using theCapabilities

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumremoteDesiredCapabilitiesfirefox

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumCapabilitiesimport orgopenqaseleniumWebDriverimport orgopenqaseleniumremoteRemoteWebDriver

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtensionExtendWith(SeleniumExtensionclass)public class RemoteWebDriverJupiterTest

DriverUrl String url = httplocalhost4444wdhub

DriverCapabilities Capabilities capabilities = firefox()

Test void testWithRemoteChrome(DriverUrl(httplocalhost4445wdhub) DriverCapabilities(browserName=chrome) RemoteWebDriver driver) exercise(driver)

Test void testWithRemoteFirefox(RemoteWebDriver driver) exercise(driver)

void exercise(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The following class contains an example which uses Chrome as browser and capabilities definedusing DriverCapabilities Concretely this example uses the mobile emulation feature provided out

24

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 27: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

of the box by Chrome (ie render the web page using small screen resolutions to emulatesmartphones)

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThatimport static orgopenqaseleniumchromeChromeOptionsCAPABILITYimport static orgopenqaseleniumremoteDesiredCapabilitieschrome

import javautilHashMapimport javautilMap

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriverimport orgopenqaseleniumremoteDesiredCapabilities

import iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithGlobalCapabilitiesJupiterTest

DriverCapabilities DesiredCapabilities capabilities = chrome() MapltString Stringgt mobileEmulation = new HashMapltString Stringgt() mobileEmulationput(deviceName Nexus 5) MapltString Objectgt chromeOptions = new HashMapltString Objectgt() chromeOptionsput(mobileEmulation mobileEmulation) capabilitiessetCapability(CAPABILITY chromeOptions)

Test void chromeTest(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Mobile testing with AppiumThe annotation DriverCapabilities can be also used to specify the desired capabilities to create aninstances of AppiumDriver to drive mobile devices (Android or iOS) If not DriverUrl is specifiedSelenium-Jupiter will start automatically an instance of Appium Server (by default in port 4723) inthe localhost after each test execution (this server is shutdown before each test) For example

25

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 28: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static orgjunitjupiterapiAssertionsassertTrue

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumWebElement

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumChromeJupiterTest

Test void testWithAndroid( DriverCapabilities( browserName=chrome deviceName=Android ) AppiumDriverltWebElementgt driver) throws InterruptedException

String context = drivergetContext() drivercontext(NATIVE_APP) driverfindElement(Byid(comandroidchromeidterms_accept))click() driverfindElement(Byid(comandroidchromeidnegative_button)) click() drivercontext(context)

driverget(httpsbonigarciagithubioselenium-jupiter) assertTrue(drivergetTitle()contains(JUnit 5 extension))

We can also specify a custom Appium Server URL changing the value of DriverUrl at field-level orparameter-level

26

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 29: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebElementimport orgopenqaseleniumremoteDesiredCapabilities

import ioappiumjava_clientAppiumDriverimport iogithubbonigarciaDriverCapabilitiesimport iogithubbonigarciaDriverUrlimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class AppiumWithGlobalOptionsChromeJupiterTest

DriverUrl String url = httplocalhost4723wdhub

DriverCapabilities DesiredCapabilities capabilities = new DesiredCapabilities() capabilitiessetCapability(browserName chrome) capabilitiessetCapability(deviceName Samsung Galaxy S6)

Test void testWithAndroid(AppiumDriverltWebElementgt driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Advanced features

Using optionsSo far we have discovered how to use different local browsers (Chrome Firefox Edge OperaSafari PhamtomJS HtmlUnit) Docker browsers (Chrome Firefox Opera) or even remote browserswith Selenium Grid In any case the default options are used Nevertheless if you have usedintensively Selenium WebDriver different questions might come to your mind

bull What if I need to specify options (eg ChromeOptions FirefoxOptions etc) to my WebDriverobject

bull What if need to specify desired capabilities (eg browser type version platform)

27

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 30: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

In order to support the advance features of Selenium WebDriver Selenium-Jupiter provides severalannotations aimed to allow a fine-grained control of the WebDriver object instantiation Theseannotations are

bull Options (field-level) Annotation to configure options (eg ChromeOptions for ChromeFirefoxOptions for Firefox EdgeOptions for Edge OperaOptions for Opera and SafariOptions forSafari)

bull Arguments (parameter-level) Used to add arguments to the options

bull Preferences (parameter-level) Used to set preferences to the options

bull Binary (parameter-level) Used to set the location of the browser binary

bull Extensions (parameter-level) User to add extensions to the browser

The annotations marked as parameter-level are applied to a single WebDriver parameter Theannotations marked as field-level are applied globally in a test class

The following example shows how to specify options for Chrome In the first test (calledheadlessTest) we are setting the argument --headless used in Chrome to work as a headlessbrowser In the second test (webrtcTest) we are using two different arguments --use-fake-device-for-media-stream and --use-fake-ui-for-media-stream used to fake user media (ie camera andmicrophone) in WebRTC applications In the third test (extensionTest) we are adding an extensionto Chrome using the Extensions annotation The value of this field is an extension file that will besearched i) using value as its relativeabsolute path ii) using value as a file name in the projectclasspath

28

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 31: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaArgumentsimport iogithubbonigarciaExtensionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class ChromeWithOptionsJupiterTest

Test void headlessTest(Arguments(--headless) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Test void webrtcTest(Arguments( --use-fake-device-for-media-stream --use-fake-ui-for-media-stream ) ChromeDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Test void extensionTest(Extensions(hello_worldcrx) ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

As introduced before this annotation Options can be used also at field-level as shown in this otherexample This test is setting to true the Firefox preferences medianavigatorstreamsfake andmedianavigatorpermissiondisabled used also for WebRTC

29

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 32: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static orghamcrestCoreMatchersequalToimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumByimport orgopenqaseleniumfirefoxFirefoxDriverimport orgopenqaseleniumfirefoxFirefoxOptions

import iogithubbonigarciaOptionsimport iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class FirefoxWithGlobalOptionsJupiterTest

Options FirefoxOptions firefoxOptions = new FirefoxOptions() Flag to use fake media for WebRTC user media firefoxOptionsaddPreference(medianavigatorstreamsfake true)

Flag to avoid granting access to user media firefoxOptionsaddPreference(medianavigatorpermissiondisabled true)

Test public void webrtcTest(FirefoxDriver driver) driverget( httpswebrtcgithubiosamplessrccontentdevicesinput-output) assertThat(driverfindElement(Byid(video))getTagName() equalTo(video))

Template testsSelenium-Jupiter takes advantage on the standard feature of JUnit 5 called test templates Testtemplates can be seen as an special kind of parameterized tests in which the test is executedseveral times according to the data provided by some extension In our case the extension isSelenium-Jupiter itself and the test template is configured using a custom file in JSON calledbrowsers scenario

Letrsquos see some examples Consider the following test A couple of things are new in this test First ofall instead of declaring the method with the usual Test annotation we are using the JUnit 5rsquosannotation TestTemplate With this we are saying to JUnit that this method is not a regular test casebut a template Second the parameter type of the method templateTest is WebDriver This is the

30

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 33: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

generic interface of Selenium WebDriver and the concise type (ie ChromeDriver FirefoxDriverRemoteWebDriver etc) will be determined by Selenium-Jupiter in runtime

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiAfterAllimport orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTest

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

The last piece we need in this test template is what we call browser scenario As introduced beforethis scenario is defined in a JSOn file following a simple notation

The path of the JSON browser scenario is established in the configuration key calledseljupbrowsertemplatejsonfile By default this key has the value classpathbrowsersjson Thismeans that the JSON scenario is defined in a file called browsersjson located in the classpath (seesection Configuration for further details about configuration)

NOTEIf the configuration key seljupbrowsertemplatejsonfile do not start with theword classpath the file will be searched using relative of absolute paths

Now imagine that the content of the file browsersjson is as follows

31

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 34: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

browsers [ [ type chrome-in-docker version latest ] [ type chrome-in-docker version latest-1 ] [ type chrome-in-docker version beta ] [ type chrome-in-docker version unstable ] ]

When we execute the template test in this case we will have four actual tests the first using thelatest version of Chrome the second using the previous to stable version of Chrome (latest-1) thethird using the beta version of Chrome (beta) and another test using the development version ofChrome (unstable) For instance if we run the test in Eclipse we will get the following output

32

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 35: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Figure 6 Example of test template execution in Eclipse

Generally speaking a browser within the JSON scenario is defined using the following parameters

bull type Type of browsers The accepted values are

chrome For local Chrome browsers

firefox For local Firefox browsers

edge For local Edge browsers

iexplorer For local Internet Explorer browsers

opera For local Opera browsers

safari For local Safari browsers

appium For local mobile emulated devices

phantomjs For local PhtanomJS headless browsers

chrome-in-docker For Chrome browsers in Docker

firefox-in-docker For Firefox browsers in Docker

opera-in-docker For Opera browsers in Docker

android For web browsers in Android devices in Docker containers

bull version Optional value for the version Wildcard for latest versions (latest latest-1 etc) areaccepted Concrete versions are also valid (eg 630 570 etc depending of the browser) Betaand unstable (ie development) versions for Chrome and Firefox are also supported (using thelabels beta and unstable labels respectively)

bull browserName As of version 220 when the type is android device the parameter browserName canbe used to select the browser in Android (chrome or browser)

bull deviceName Also for android type the device type can be specified (Samsung Galaxy S6 Nexus 4

33

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 36: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Nexus 5 etc)

Finally more than one parameters can be defined in the test template For instance consider thefollowing test in which a couple of WebDriver parameters are declared in the test template

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class TemplateTwoBrowsersTest

TestTemplate void templateTest(WebDriver driver1 WebDriver driver2) driver1get(httpsbonigarciagithubioselenium-jupiter) driver2get(httpsbonigarciagithubioselenium-jupiter) assertThat(driver1getTitle() containsString(JUnit 5 extension for Selenium)) assertThat(driver2getTitle() containsString(JUnit 5 extension for Selenium))

The JSON scenario should be defined accordingly Each browser array in this case (for each testtemplate execution) should declare two browsers For instance using the following JSON scenariothe first execution will be based on Chrome in Docker (first parameter) and Firefox in Docker(second parameter) and the second execution will be based on a local Chrome (first parameter)and the headless browser PhantomJS (second parameter)

34

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 37: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

browsers [ [ type chrome-in-docker type firefox-in-docker ] [ type chrome type phantomjs ] ]

If we execute this test using in GUI the JUnit tab shows two tests executed with the values definedin the JSON scenario

Figure 7 Example of test template execution (with two parameters) in Eclipse

As of version 220 Selenium-Jupiter allows to configure the browser scenario programmaticallyusing the JUnit 5 RegisterExtension annotation To that aim the method addBrowsers of theSeleniumExtension instance is used to add different browser(s) to the scenario In the followingexample the test is executed twice one using Chrome and the second using Firefox

35

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 38: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiBeforeAllimport orgjunitjupiterapiTestTemplateimport orgjunitjupiterapiextensionRegisterExtensionimport orgopenqaseleniumWebDriver

import iogithubbonigarciaBrowserBuilderimport iogithubbonigarciaBrowsersTemplateBrowserimport iogithubbonigarciaSeleniumExtension

public class TemplateRegisterTest

RegisterExtension static SeleniumExtension seleniumExtension = new SeleniumExtension()

BeforeAll static void setup() Browser chrome = BrowserBuilderchrome()build() Browser firefox = BrowserBuilderfirefox()build() seleniumExtensionaddBrowsers(chrome) seleniumExtensionaddBrowsers(firefox)

TestTemplate void templateTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

Generic driverAs of version 210 Selenium-Jupiter allows to use a configurable WebDriver object This genericdriver is declared as usual (ie as test method or constructor parameter) using the typeRemoteWebDriver or WebDriver The concrete type of browser to be used is established using theconfiguration key seljupdefaultbrowser The default value for this key is chrome-in-docker All thevalues used in the template test defined in the previous section (ie chrome firefox edge chrome-in-docker firefox-in-docker android etc) can be used also to define the type of browser in this mode

For instance the following test if no additional configuration is done will use Chrome in Docker asbrowser

36

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 39: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import static orghamcrestCoreMatcherscontainsStringimport static orghamcrestMatcherAssertassertThat

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumWebDriver

import iogithubbonigarciaSeleniumExtension

ExtendWith(SeleniumExtensionclass)public class GenericTest

Test void genericTest(WebDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

If the resolution of this browser finishes with exception (for instance when executing the test in ahost without Docker) a list of browser fallback will be used This list is managed using theconfiguration key seljupdefaultbrowserfallback By default this key has the valuechromefirefoxsafariedgephantomjs meaning that the first fallback browser is a local Chromethen local Firefox then local Safari then local Edge and finally PhantomJS (headless browser)

The version of the generic browser (in case of Docker browsers) is managed with the keyseljupdefaultversion (latest by default) The versions of the fallback browsers can be alsomanaged this time using the configuration key seljupdefaultbrowserfallbackversion

Integration with JenkinsSelenium-Jupiter provides seamless integration with Jenkins through one of its plugins the Jenkinsattachment plugin The idea is to provide the ability to attache output files (typically PNGscreenshots and MP4 recordings of Docker browsers) and keep these files attached to the jobexecution This is done in Selenium-Jupiter setting the configuration key seljupoutputfolder to anspecial value surefire-reports

When this configuration key is configured with that value Selenium-Jupiter will store the generatedfiles in the proper folder in a way that the Jenkins attachment plugin is able to find those files andexport them in the Jenkins GUI For instance consider the following test when is executed inJenkins (with the attachment plugin) and the following configuration

mvn clean test -Dtest=DockerFirefoxWithOptionsJupiterTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

37

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 40: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

In this case at the the execution of this test two recordings in MP4 and two screenshots in PNG willbe attached to the job as follows

Figure 8 Example of test execution through Jenkins with attachments

We can watch the recording simply clicking in the attached MP4 files

38

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 41: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Figure 9 Example of test execution through Jenkins with attachements

Test template are also compatible with this feature For instance consider the following test testWhen is executed in Jenkins using the configuration below the following attachments will beavailable on Jenkins

mvn clean test -Dtest=TemplateTest -Dseljuprecording=true-Dseljupoutputfolder=surefire-reports -Dseljupscreenshotattheendoftests=true

39

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 42: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Figure 10 Example of template test execution through Jenkins with attachments

And we will be able to watch the recording

40

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 43: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Figure 11 Example of template test execution through Jenkins with attachments

ConfigurationDefault configuration parameters for Selenium-Jupiter are set in the selenium-jupiterproperties fileThe following table summarizes all the configuration keys available

Table 3 Configuration keys in Selenium-Jupiter

Configuration key Description Default value

seljupvnc Check VNC session for Dockerbrowsers

false

seljupvncscreenresolution Screen resolution of VNCsessions (formatltwidthgtxltheightgtxltcolors-depthgt)

1920x1080x24

seljupvnccreateredirecthtmlpage

Redirect VNC URL to HTMLpage

false

seljupvncexport Java property name in whichthe VNC URL will be exported

vncsessionurl

41

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 44: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Configuration key Description Default value

seljuprecording Record Docker browser session(in MP4 format)

false

seljuprecordingvideoscreensize

Video screen size for recordings(width and height)

1024x768

seljuprecordingvideoframerate

Video frame rate for recordings 12

seljuprecordingimage Docker image for recordings selenoidvideo-recorderlatest

seljupoutputfolder Output folder for recordingsscreenshots and HTML redirectpages

seljupscreenshotattheendoftests

Make screenshots at the end ofthe test

false

seljupscreenshotformat Format for screenshots base64

seljupexceptionwhennodriver

Throw exception in case ofexception or not

true

seljupbrowsertemplatejsonfile

Browsers scenario (JSON) path classpathbrowsersjson

seljupdefaultbrowser Browser for generic driver chrome-in-docker

seljupdefaultversion Version for generic driver latest

seljupdefaultbrowserfallback

Fallback browser list forgeneric driver

chromefirefoxsafariedgephantomjs

seljupdefaultbrowserfallbackversion

Fallback version list for genericdriver

latestlatestlatestlatestlatest

seljupbrowserlistfromdockerhub

Update Docker images list fromDocker Hub

true

seljupbrowsersessiontimeoutduration

Session timeout for Dockerbrowsers (in Golang durationformat)

1m0s

seljupselenoidimage Selenoid (Golang SeleniumHub) Docker iamage

aerokubeselenoid160

seljupselenoidport Selenoid port 4444

seljupselenoidvncpassword VNC password for Selenoidsessions

selenoid

seljupnovncimage noVNC Docker image psharkeynovnc33-t6

seljupnovncport noVNC Docker port 8080

seljupchromeimageformat Selenoid Docker images formatfor Chrome with VNC

selenoidvncchrome_s

seljupchromefirstversion First version of Docker Chrome(used whenseljupbrowserlistfromdockerhub =false)

480

42

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 45: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Configuration key Description Default value

seljupchromelatestversion Latest version of DockerChrome (used whenseljupbrowserlistfromdockerhub =false)

650

seljupchromepath Path for Hub when usingChrome in Docker as browser

seljupchromebetaimage Selenoid Docker image formatfor Chrome beta

elastestbrowserschromebeta

seljupchromebetapath Path for Hub when usingChrome beta in Docker asbrowser

wdhub

seljupchromeunstableimage Selenoid Docker image formatfor Chrome unstable

elastestbrowserschromeunstable

seljupchromeunstablepath Path for Hub when usingChrome unstable in Docker asbrowser

wdhub

seljupfirefoximageformat Selenoid Docker images formatfor Firefox with VNC

selenoidvncfirefox_s

seljupfirefoxfirstversion First version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

36

seljupfirefoxlatestversion Latest version of Docker Firefox(used whenseljupbrowserlistfromdockerhub =false)

590

seljupfirefoxpath Path for Hub when usingFirefox in Docker as browser

wdhub

seljupfirefoxbetaimage Selenoid Docker image formatfor Firefox beta

elastestbrowsersfirefoxbeta

seljupfirefoxbetapath Path for Hub when usingFirefox beta in Docker asbrowser

wdhub

seljupfirefoxunstableimage Selenoid Docker image formatfor Firefox unstable

elastestbrowsersfirefoxnightly

seljupfirefoxunstablepath Path for Hub when usingFirefox beta in Docker asunstable

wdhub

seljupoperaimageformat Selenoid Docker images formatfor Opera with VNC

selenoidvncopera_s

seljupoperafirstversion First version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

330

43

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 46: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Configuration key Description Default value

seljupoperalatestversion Latest version of Docker Opera(used whenseljupbrowserlistfromdockerhub =false)

510

seljupoperapath Path for Hub when using Operain Docker as browser

seljupandroiddefaultversion

Default version of Androiddevices in Doker

711

seljupandroidimageapi21linux

Docker image for version 501of Android devices in Linux

butomo1989docker-android-x86-50109-p5

seljupandroidimageapi22linux

Docker image for version 511of Android devices in Linux

butomo1989docker-android-x86-51109-p5

seljupandroidimageapi23linux

Docker image for version 60 ofAndroid devices in Linux

butomo1989docker-android-x86-6009-p5

seljupandroidimageapi24linux

Docker image for version 70 ofAndroid devices in Linux

butomo1989docker-android-x86-7009-p5

seljupandroidimageapi25linux

Docker image for version 711of Android devices in Linux

butomo1989docker-android-x86-71109-p5

seljupandroidimageapi21osxwin

Docker image for version 501of Android devices in Mac andWindows

butomo1989docker-android-arm-50109-p5

seljupandroidimageapi22osxwin

Docker image for version 511of Android devices in Mac andWindows

butomo1989docker-android-arm-51109-p5

seljupandroidimageapi23osxwin

Docker image for version 60 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-6009-p5

seljupandroidimageapi24osxwin

Docker image for version 70 ofAndroid devices in Mac andWindows

butomo1989docker-android-arm-7009-p5

seljupandroidimageapi25osxwin

Docker image for version 711of Android devices in Mac andWindows

butomo1989docker-android-arm-71109-p5

seljupandroidnovncport Internal port of noVNC inDocker containers for Androiddevices

6080

seljupandroidappiumport Internal port of Appium serverin Docker containers forAndroid devices

4723

seljupandroiddevicename Default device name forAndroid in Docker

Samsung Galaxy S6

seljupandroidbrowsername Default browser name forAndroid in Docker

chrome

44

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 47: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

Configuration key Description Default value

seljupandroiddevicetimeoutsec

Timeout (in seconds) to waitAndroid devices to be available

200

seljupdockerserverurl URL to connect with the DockerHost

seljupdockerwaittimeoutsec

Timeout (in seconds) to wait forDocker container

20

seljupdockerpolltimems Poll time (in ms) for asking toDocker container if alive

200

seljupdockerdefaultsocket Default Docker socket path varrundockersock

seljupdockerhuburl Docker Hub URL httpshubdockercom

seljupdockerstoptimeoutsec

Timeout in seconds to stopDocker containers at the end oftests

5

seljupdockerapiversion Docker API version 135

seljupdockernetwork Docker network bridge

seljupdockertimezone Timezone for browsers inDocker containers

EuropeMadrid

seljupproperties Location of the properties files(in the project classpath)

selenium-jupiterproperties

seljupseleniumserverurl Selenium Server URL to beused instead of DriverUrl orfor browsers in Docker

These properties can be overwritten in different ways As of version 210 of Selenium-Jupiter theconfiguration manager can be used

SeleniumJupiterconfig()setVnc(true)SeleniumJupiterconfig()setRecording(true)SeleniumJupiterconfig()useSurefireOutputFolder()SeleniumJupiterconfig()setBrowserListFromDockerHub(false)SeleniumJupiterconfig()wdm()setForceCache(true)SeleniumJupiterconfig()wdm()setOverride(true)

We can also use Java system properties for example

SystemsetProperty(seljuprecording true)

i or by command line for example

-Dseljuprecording=true

Moreover the value of these properties can be overridden by means of environmental variables

45

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 48: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

The name of these variables result from putting the name in uppercase and replacing the symbol by _ For example the property seljuprecording can be overridden by the environment variableSEL_JUP_RECORDING

Tuning WebDriverManagerAs introduced before Selenium-Jupiter internally uses WebDriverManager to manage the requiredbinary to control localc browsers This tool can be configured in several ways for example to forceusing a given version of the binary (by default it tries to use the latest version) or force to use thecache (instead of connecting to the online repository to download the binary artifact) For furtherinformation about this configuration capabilities please take a look to the WebDriverManagerdocumentation

In this section we are going to present a couple of simple examples tuning somehowWebDriverManger The following example shows how to force a version number for a binaryconcretely for Edge

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumedgeEdgeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class EdgeSettingVersionJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setDriverVersion(314393)

Test void webrtcTest(EdgeDriver driver) driverget(httpwwwseleniumhqorg) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

This other example shows how to force cache (ie binaries previously downloaded byWebDriverManager) to avoid the connection with online repository to check the latest version

46

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 49: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

import orgjunitjupiterapiTestimport orgjunitjupiterapiextensionExtendWithimport orgopenqaseleniumchromeChromeDriver

import iogithubbonigarciaSeleniumExtensionimport iogithubbonigarciaSeleniumJupiter

ExtendWith(SeleniumExtensionclass)public class ForceCacheJupiterTest

BeforeAll static void setup() SeleniumJupiterconfig()wdm()setForceCache(true)

Test public void test(ChromeDriver driver) driverget(httpsbonigarciagithubioselenium-jupiter) assertThat(drivergetTitle() containsString(JUnit 5 extension for Selenium))

ScreenshotsSelenium-Jupiter provides several built-in features for making screenshots for each of the browsersessions at the end of the test These screenshots can be encoded as Base64 or stored as PNGimages The following configuration keys are used to control the way and format in whichscreenshots are made

bull seljupscreenshotattheendoftests This key indicates whether or not screenshots will bemade at the end of every browser session The accepted valued for this configuration key are

true Screenshots are always taken at the end of tests

false Screenshots are not taken at the end of tests

whenfailure Screenshots are only taken if the test fails

bull seljupscreenshotformat Format for the screenshot The accepted values for this key are two

base64 Base64 screenshots are logged using the debug level of (Simple Logging Facade forJava (SLF4J) You can copyamppaste the resulting Base 64 string in the URL bar of any browserand watch the screenshot

png Screenshots are stored as PNG images The output folder for these images is configuredusing the configuration key seljupoutputfolder (the default value of this property is iethe local folder)

Take into account that a big base64 string will be added to your logs if this option if configured Thisfeature can be especially useful for build server in the cloud (such as Travis CI) in which we donrsquot

47

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 50: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

have access to the server file system but can track easily the test output log

------------------------------------------------------- T E S T S-------------------------------------------------------Running iogithubbonigarciatestbasicChromeJupiterTest2017-12-13 024153 [main] DEBUG igbonigarciaSeleniumExtension - Screenshot (inBase64) at the end of session 5712cce700bb76d8f5f5d65a00e2c7bc (copyamppaste this stringas URL in browser to watch it)dataimagepngbase64iVBORw0KGgoAAAANSUhEUgAAAykAAANaCAIAAAACvpRSAAAgAElEQVR4nOy9e3xV1Zn1lr384t5+RyCDmBhJBwSRACBAqhXFQsYlGLZeygrWVGbalTtVU72gv9fgfnK3Yq36mdqTqOLTL1R8fyq2Wk3kCGSqEMlxKQiyQICZAAJySHnJyT5Nz2ZX3ODGEk71DDuSCuN4vXrySnXX2WWfvtc767Od51vMQxhg4HA6Hw+FwOOkTDofTfQkdiH5wOBwOh8PhcEzh2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOZDg2ovD4XA4HA5n8ODai8PhcDgcDmfw4NqLw+FwOBwOp55wx+YPUnrr04HA6Hw+Fw+pOk8LKSX1x7cTgcDofD4fQb3SWXqfzi2onr2SgWY2TMdyRZMNENknWYTIo75WxuUWNCij9k178gCKO3BHLtkeQjiMYEgXy668f5nl+x5798mYAvFysJUmckrGBLMvdC0SlJSUjrXpwn3Ba6MgAlILbL+85fAruDfRSl08WQBr2oDm4uNtmZOPKRm7GSgptWXBFJPrAAAAl0lEQVS4biJEm74sxVmrvz+U468MXDMRZc7zY5Aj1uDndWEG2gCWk+R5ARMgl5aZrga3N7XBT9vCbxrBWPjx396tsQz8LL4foDPzSVlH4crofHwrFXxyDZx1xHaWN7EjwAiTf69Gf8G1O5SUDCBnj2EW8huvfnTLaFNSMsD043+89QUmwCzyUhp9AFYTDCDwBA0OZPpbBVqwAAAABJRU5ErkJggg==Tests run 2 Failures 1 Errors 0 Skipped 1 Time elapsed 7219 sec ltltlt FAILURE- in iogithubbonigarciatestbasicChromeJupiterTesttestWithOneChrome(ChromeDriver) Time elapsed 6594 sec ltltlt FAILURE

Known issues

Testing localhostA daily use case in web development is testing an web application deployed in a local server(httplocalhostportpath) In the case of using Docker browsers to test this web application weneed to be aware that localhost inside a Docker container is not the local host anymore but thecontainer To handle this issue different approaches can be taken

bull If your host (ie the local machine running the tests and hosting the web application under test)is Linux Docker creates a bridge named docker0 by default Both the Docker host and the Dockercontainers have an IP address on that bridge We can find out the equivalent IP address tolocalhost using the following command (in this example the address 1721701 will be used toreplace localhost in our tests)

48

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 51: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

$ ip addr show docker04 docker0 ltNO-CARRIERBROADCASTMULTICASTUPgt mtu 1500 qdisc noqueue state DOWNgroup default linkether 0242b48310c8 brd ffffffffffff inet 172170116 scope global docker0 valid_lft forever preferred_lft forever

bull If your host is Mac and using Docker for Mac we can use the special DNS namedockerformachostinternal which will resolve to the internal IP address used by the host

bull If your host is Windows and using Docker for Windows we can use the special DNS namedockerforwinhostinternal

Using old versions of SeleniumSelenium-Jupiter requires Selenium 3 In fact selenium-java 3x is incorporated as transitivedependency when using Selenium-Jupiter Nevertheless it might occur that an old version ofSelenium (eg 2x) is used in a project In that case Selenium-Jupiter will typically fail as follows

orgjunitjupiterapiextensionParameterResolutionException Failed to resolveparameter [] in executable [] atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava221) Caused by javalangNoClassDefFoundError orgopenqaseleniumMutableCapabilities at javalangClassgetDeclaredConstructors0(Native Method) at javalangClassprivateGetDeclaredConstructors(Unknown Source) at javalangClassgetConstructor0(Unknown Source) at javalangClassgetDeclaredConstructor(Unknown Source) atiogithubbonigarciaSeleniumExtensiongetDriverHandler(SeleniumExtensionjava228) atiogithubbonigarciaSeleniumExtensionresolveParameter(SeleniumExtensionjava175) atorgjunitjupiterengineexecutionExecutableInvokerresolveParameter(ExecutableInvokerjava207)

The solution is forcing the latest version of selenium-java to 3x

For example this issue is likely to happen in Spring-Boot 1x projects When using a Spring-Boot 1xparent Selenium 2 artifacts versions are established by default To solve it we need to force at leastthe following Selenium artifacts

49

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 52: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

ltpropertiesgt ltseleniumversiongt3110ltseleniumversiongt ltpropertiesgt

ltdependenciesgt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-javaltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-apiltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-chrome-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-firefox-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependencygt ltgroupIdgtorgseleniumhqseleniumltgroupIdgt ltartifactIdgtselenium-remote-driverltartifactIdgt ltversiongt$seleniumversionltversiongt ltscopegttestltscopegt ltdependencygt ltdependenciesgt

Recordings in Windows or MacDocker for WindowsMac only mounts by default the home of your user (eg CUsersyour-user inWindows) If Selenium-Jupiter is executed from a different parent folder of that home it wonrsquot bepossible to write the MP4 recording (by default it uses the current folder ie ) This configurationcan be changed using the default mappings of in Docker for WindowsMac settings

As an alternative the value of the configuration key seljupoutputfolder of Selenium-Jupiter canbe used to some path inside the user folder (eg CUseryour-userwhatever) The MP4 recordingshould end in there

50

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About
Page 53: Selenium-Jupiter: JUnit 5 extension for Selenium · On the other hand, Selenium is a testing framework which allows to control local (Selenium WebDriver) or remote ... ("JUnit 5 extension

AboutSelenium-Jupiter (Copyright copy 2017-2018) is a project created by Boni Garcia (boni_gg) licensedunder Apache 20 License This documentation is released under the terms of CC BY 30 (alsoavailable in PDF) There are several ways to get in touch with Selenium-Jupiter

bull Questions about Selenium-Jupiter are supposed to be discussed in StackOverflow using the tagselenium-jupiter

bull Comments suggestions and bug-reporting should be done using the GitHub issues

bull If you think Selenium-Jupiter can be enhanced consider contribute to the project by means of apull request

51

  • Selenium-Jupiter JUnit 5 extension for Selenium
  • Table of Contents
  • Quick reference
  • Local browsers
    • Chrome
    • Firefox
    • Edge
    • Opera
    • Safari
    • PhamtomJS
    • HtmlUnit
      • Docker browsers
        • Chrome
        • Firefox
        • Opera
        • Android
        • Remote sessions (VNC)
        • Recordings
        • Performance tests
        • Interactive mode
          • Remote browsers
            • Using capabilities
            • Mobile testing with Appium
              • Advanced features
                • Using options
                • Template tests
                • Generic driver
                • Integration with Jenkins
                  • Configuration
                    • Tuning WebDriverManager
                    • Screenshots
                      • Known issues
                        • Testing localhost
                        • Using old versions of Selenium
                        • Recordings in Windows or Mac
                          • About