Exploring Selenium Interactions with the Kotlin REPL

Brian Grogan Jr.
Qualitas Ex Machina
4 min readJul 7, 2020
Kotlin REPL

I’m a true believer in the power of interactive coding sessions. I’ve been really inspired by the ideas of Chris Granger’s Light Table and Bret Victor’s Learnable Programming. And I think these interactive coding techniques can be especially useful when applied to the first phase of developing a Selenium UI test.

To start, we use a technique I explained in an earlier post to load a third-party library into the Kotlin REPL:

$ ivy -dependency org.seleniumhq.selenium selenium-java 3.141.59 -cachepath classes $ kotlin -cp $(< classes)
Welcome to Kotlin version 1.3.72 (JRE 1.8.0_252-b09)
Type :help for help, :quit for quit
>>>

With the Selenium library loaded into the REPL, we can import a few essential classes, and instantiate a WebDriver object for Google Chrome:

$ kotlin -cp $(< classes)
>>> import org.openqa.selenium.By
>>> import org.openqa.selenium.chrome.ChromeDriver
>>> val wd = ChromeDriver()

After instantiating the WebDriver (ChromeDriver) object, an instance of the Chrome browser opens, controlled by the Selenium code in our active REPL session.

For this example, we’ll try testing the Help feature of the Citi Bike website. The first Selenium action required is to navigate to the website using the Webdriver#get method:

>>> wd.get("https://www.citibikenyc.com")

When we type this line of code and press Enter, the Selenium-controlled browser navigates to the website. Switch focus to the browser window (on macOS, Command + Tab), look for the “Help” link, right-click the link, and choose Inspect.

Inspect the Help Link

In the Developer Tools panel, we can see that the text of the link, “Help”, makes a suitable value for a selector.

Developer Tools Panel

In the REPL session, use the By class to specify a linkText selector for the “Help” link, and try finding the element with WebDriver#findElement:

>>> wd.findElement(By.linkText("Help"))
res5: org.openqa.selenium.WebElement!

It looks like the linkText selector successfully found a WebElement, so we can assign the value of the REPL result to a Kotlin value, and then perform a WebElement#click action:

>>> val help = res5
>>> help.click()

On the Help page of the website, there is a search form where we can search for topics of information. We will inspect the search form to look for a suitable selector value.

Inspect the Search Form

In the Developer Tools panel, we can see that one possible selector value is a CSS expression that combines the <input> tag with the [type] attribute and the attribute value “search”. In the REPL session, we use the By class to specify a cssSelector and call findElement again:

>>> wd.findElement(By.cssSelector("input[type='search']"))
res6: org.openqa.selenium.WebElement!

The cssSelector found the search form element, so we can assign the WebElement to a Kotlin value, and enter the text “ebike” with WebElement#sendKeys to search for information about e-bikes (electric bikes):

>>> val search = res6
>>> search.sendKeys("ebike")

With the search text entered, an auto-complete element appears. In the Developer Tools panel, if we scroll down, we can find the auto-complete element inserted near the end of the <body> element.

zd-autocomplete-option

Let’s use the tag name of the auto-complete option, <zd-autocomplete-option>, to create a cssSelector and find the element:

>>> wd.findElement(By.cssSelector("zd-autocomplete-option"))
res9: org.openqa.selenium.WebElement!

The cssSelector returned a valid WebElement, so we can assign the WebElement to a value, and click it:

>>> val result = res9
>>> result.click()

And after clicking the result, we arrive at the page containing the correct information about using e-bikes with the Citi Bike service 👍

Riding with an ebike

Finally, to quit the browser and the REPL session:

>>> wd.quit()
>>> :quit

If you want to re-use this code without re-typing a bunch of things, you can copy the code from the terminal and paste it into a .kt source code file. In my favorite terminal program, iTerm2, there is an especially useful command “Select Output of Last Command” that is really helpful for this kind of thing.

Working with a REPL session and a Selenium-controlled browser window gives you a much more interactive test development experience. It encourages a very fast feedback loop of finding selector values, trying them out, and using the results to perform actions on the elements. You can very quickly figure out which selectors and actions are going to work, and which ones will fail.

I use REPL sessions in all of the development environments I work in: Python, JavaScript, Clojure. I’m glad Kotlin included this productivity-enhancing feature too. It helps to speed up my development process every day.

--

--

Brian Grogan Jr.
Qualitas Ex Machina

Software Quality Engineer fighting for truth, justice, and better quality apps. Thinks a lot about Automation and CI/CD, in both practical and abstract terms.