SlideShare a Scribd company logo
Excuse me, sir,
do you have a
moment to talk
about tests in
Kotlin?
—
Leonid Rudenko
Why?
—
_2
Why?
—
_3
Why?
—
Selenium Camp 2016
#4 Make	Your	Automation																					ier
_4
What’s going on here
—
• What is Kotlin?
• Problems Kotlin solves
• Demo
Excuse me, sir, do you have a moment to talk about tests in Kotlin? _5
What’s going on here
—
• What is Kotlin?
• Problems Kotlin solves
• Demo
Excuse me, sir, do you have a moment to talk about tests in Kotlin? _6
Kotlin is...
—
• JVM language from JetBrains – Java 6+
1. What is Kotlin? _7
Kotlin is...
—
• JVM language
• Statically typed
1. What is Kotlin? _8
Kotlin is...
—
• JVM language
• Statically typed
• Multi-paradigm – OOP & functional
1. What is Kotlin? _9
Kotlin is...
—
• JVM language
• Statically typed
• Multi-paradigm
• Pragmatic
1. What is Kotlin? _10
Kotlin is...
—
• JVM language
• Statically typed
• Multi-paradigm
• Pragmatic
• Democratic
1. What is Kotlin? _11
Kotlin is...
—
• JVM language
• Statically typed
• Multi-paradigm
• Pragmatic
• Democratic
• Safe
1. What is Kotlin? _12
Kotlin is...
—
• JVM language
• Statically typed
• Multi-paradigm
• Pragmatic
• Democratic
• Safe
• Concise
1. What is Kotlin? _13
Brevity	is	the	sister	of	talent.
- Anton	Chekhov	-
Kotlin is...
—
• JVM language
• Statically typed
• Multi-paradigm
• Pragmatic
• Democratic
• Safe
• Concise
• Interoperable
1. What is Kotlin? _14
Kotlin is...
—
• JVM language
• Statically typed
• Multi-paradigm
• Pragmatic
• Democratic
• Safe
• Concise
• Interoperable
1. What is Kotlin? _15
Kotlin 1.0
—
• 15 Feb 2016 – backward compatibility
1. What is Kotlin? _16
Kotlin 1.0
—
• 15 Feb 2016
• kotlinc, Intellij IDEA (plugin), Eclipse (plugin), NetBeans (plugin)
1. What is Kotlin? _17
Kotlin 1.0
—
• 15 Feb 2016
• kotlinc, Intellij IDEA (plugin), Eclipse (plugin), NetBeans (plugin)
• Open source https://github.com/jetbrains/kotlin
1. What is Kotlin? _18
1. What is Kotlin? _19
_20
Google Trends: Kotlin 1y
—
1. What is Kotlin? _21
Google Trends: Kotlin vs Groovy 1y
—
1. What is Kotlin? _22
Where Kotlin is used
—
• JetBrains products
1. What is Kotlin? _23
Where Kotlin is used
—
• JetBrains products
• Android
1. What is Kotlin? _24
Where Kotlin is used
—
• JetBrains products
• Android
• Server & Desktop
1. What is Kotlin? _25
Where Kotlin is used
—
• JetBrains products
• Android
• Server & Desktop
• Gradle	3.0 https://github.com/gradle/gradle-script-kotlin
1. What is Kotlin? _26
Where Kotlin is used
—
• JetBrains products
• Android
• Server & Desktop
• Gradle	3.0
• (Web) Test Automation
1. What is Kotlin? _27
Test Automation: why Kotlin?
—
• Syntax similar to Java
1. What is Kotlin? _28
Test Automation: why Kotlin?
—
• Syntax similar to Java
• Clean test code
Conciseness
Easy to read == easy to understand
Collective code ownership, effective code review
1. What is Kotlin? _29
Test Automation: why Kotlin?
—
• Syntax similar to Java
• Clean test code
Conciseness
Easy to read == easy to understand
Collective code ownership, effective code review
• Safe test code
1. What is Kotlin? _30
What’s going on here
—
• What is Kotlin?
• Problems Kotlin solves
• Demo
Excuse me, sir, do you have a moment to talk about tests in Kotlin? _31
Kotlin features
—
• Extension functions
• Data classes
• Lambda functions
• Smart cast
• Type inference
• Null safety
2. Problems Kotlin solves _32
1. Problem: Maps and Lists in Java
—
// Java
Map<Integer, Credentials> users = new HashMap<>();
users.put(1, new Credentials("vasya", "123456"));
users.put(2, new Credentials("johny", "qwerty"));
users.put(3, new Credentials("admin", "admin"));
List<Integer> responseCodes = new ArrayList<>();
responseCodes.add(200);
responseCodes.add(302);
2. Problems Kotlin solves _33
1. Solution: Kotlin collections
—
// Kotlin
val users = mapOf(
1 to Credentials("vasya", "123456"),
2 to Credentials("johny", "qwerty"),
3 to Credentials("admin", "admin"))
val responseCodes = listOf(200, 302)
2. Problems Kotlin solves _34
1. Collections: Map
—
// Kotlin
val users = mapOf(
1 to Credentials("vasya", "123456"),
2 to Credentials("johny", "qwerty"),
3 to Credentials("admin", "admin"))
Map<Integer, Credentials>
new
users.put(4, Credentials("...", "..."))
2. Problems Kotlin solves _35
1. Collections: Traversing a map
—
// Java
for (Map.Entry<Integer, Credentials> pair : users.entrySet()) {
System.out.println(pair.getKey() + "->" + pair.getValue());
}
// Kotlin
for ((id, creds) in users) {
println("$id->$creds")
}
2. Problems Kotlin solves _36
1. Collections: forEach, filters, sorting...
—
// Kotlin
val link = driver.findElements("a").firstOrNull {
it.text == "Selenium Camp"
}
2. Problems Kotlin solves _37
1. Collections: Java & Groovy
—
• Java 7
• Java 8 (Stream API)
• Groovy
2. Problems Kotlin solves _38
1. Collections: forEach, filters, sorting...
—
2. Problems Kotlin solves _39
// Kotlin
val link = driver.findElements("a").firstOrNull {
it.text == "Selenium Camp"
}
2. Problem: framework can’t do what you need it to do
—
// Java
public static List<WebElement> findElements(WebDriver driver,
String selector) {
return driver.findElements(By.cssSelector(selector));
}
findElements(driver, "a");
2. Problems Kotlin solves _40
2. Problem: framework can’t do what you need it to do
—
2. Problems Kotlin solves _41
2. Solution: Extension functions
—
// Kotlin
fun WebDriver.findElements(selector: String): List<WebElement>{
return this.findElements(By.cssSelector(selector))
}
driver.findElements("a")
2. Problems Kotlin solves _42
2. Extension functions
—
// Kotlin
fun WebDriver.findElements(selector: String): List<WebElement>{
return this.findElements(By.cssSelector(selector))
}
driver.findElements("a")
2. Problems Kotlin solves _43
2. Extension functions
—
// Kotlin
fun WebDriver.findElements(selector: String): List<WebElement>{
return this.findElements(By.cssSelector(selector))
}
driver.findElements("a")
2. Problems Kotlin solves _44
2. Extension functions
—
// Kotlin
fun WebDriver.findElements(selector: String): List<WebElement>{
return this.findElements(By.cssSelector(selector))
}
driver.findElements("a")
2. Problems Kotlin solves _45
2. Extension functions: Java & Groovy
—
• Java
• Groovy (Extension Modules)
2. Problems Kotlin solves _46
3. Problem: small classes are not small
—
// Java
public class Credentials {
private final String username;
private final String password;
}
2. Problems Kotlin solves _47
3. Problem: small classes are not small
—
// Java
public class Credentials {
private final String username;
private final String password;
public Credentials(String username, String password) {
this.username = username;
this.password = password;
}
}
2. Problems Kotlin solves _48
3. Problem: small classes are not small
—
// Java
public class Credentials {
private final String username;
private final String password;
public Credentials(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() { return username; }
public String getPassword() { return password; }
}
2. Problems Kotlin solves _49
3. Problem: small classes are not small
—// Java
public class Credentials {
private final String username;
private final String password;
public Credentials(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() { return username; }
public String getPassword() { return password; }
@Override
public String toString() {
return username + '/' + password;
}
}
2. Problems Kotlin solves _50
3. Problem: small classes are not small
—// Java
public class Credentials {
private final String username;
private final String password;
public Credentials(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() { return username; }
public String getPassword() { return password; }
@Override
public String toString() {
return username + '/' + password;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Credentials that = (Credentials) o;
if (username != null ? !username.equals(that.username) : that.username != null) return false;
return password != null ? password.equals(that.password) : that.password == null;
}
@Override
public int hashCode() {
int result = username != null ? username.hashCode() : 0;
return 31 * result + (password != null ? password.hashCode() : 0);
}
}
2. Problems Kotlin solves _51
3. Problem: 27 lines
—// Java
public class Credentials {
private final String username;
private final String password;
public Credentials(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() { return username; }
public String getPassword() { return password; }
@Override
public String toString() {
return username + '/' + password;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Credentials that = (Credentials) o;
if (username != null ? !username.equals(that.username) : that.username != null) return false;
return password != null ? password.equals(that.password) : that.password == null;
}
@Override
public int hashCode() {
int result = username != null ? username.hashCode() : 0;
return 31 * result + (password != null ? password.hashCode() : 0);
}
}
2. Problems Kotlin solves _52
3. Solution: direct to Kotlin – 18 lines
—// Java
public class Credentials {
private final String username;
private final String password;
public Credentials(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() { return username; }
public String getPassword() { return password; }
@Override
public String toString() {
return username + '/' + password;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Credentials that = (Credentials) o;
if (username != null ? !username.equals(that.username) : that.username != null)
return false;
return password != null ? password.equals(that.password) : that.password == null;
}
@Override
public int hashCode() {
int result = username != null ? username.hashCode() : 0;
return 31 * result + (password != null ? password.hashCode() : 0);
}
}
2. Problems Kotlin solves _53
// Kotlin
class Credentials {
private val username: String
private val password: String
constructor(username: String, password: String) {
this.username = username
this.password = password
}
fun getUsername(): String { return username }
fun getPassword(): String { return password }
override fun toString() = username + '/' + password
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as Credentials
return username == other.username && password == other.password
}
override fun hashCode() = 31 * username.hashCode() + password.hashCode()
}
3. Solution: remove getters – 16 lines
—// Kotlin
class Credentials {
val username: String
val password: String
constructor(username: String, password: String) {
this.username = username
this.password = password
}
//fun getUsername(): String { return username }
//fun getPassword(): String { return password }
override fun toString() = username + '/' + password
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as Credentials
return username == other.username && password == other.password
}
override fun hashCode() = 31 * username.hashCode() + password.hashCode()
}
2. Problems Kotlin solves _54
3. Solution: primary constructor – 10 lines
—// Kotlin
class Credentials(val username: String, val password: String) {
//val username: String
//val password: String
//constructor(username: String, password: String) {
// this.username = username
// this.password = password
//}
override fun toString() = username + '/' + password
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as Credentials
return username == other.username && password == other.password
}
override fun hashCode() = 31 * username.hashCode() + password.hashCode()
}
2. Problems Kotlin solves _55
3. Solution: data class – 1 line
—
// Kotlin
data class Credentials(val username: String, val password: String) {
//override fun toString() = username + '/' + password
//override fun equals(other: Any?): Boolean {
// if (this === other) return true
// if (other?.javaClass != javaClass) return false
// other as Credentials
// return username == other.username && password == other.password
//}
//override fun hashCode() = 31 * username.hashCode() + password.hashCode()
}
2. Problems Kotlin solves _56
3. Solution: Kotlin data classes
—
// Kotlin
data class Credentials(val username: String, val password: String)
val creds = Credentials("a", "b")
println(creds.username) // a
creds.username = "you can't do that"
println(creds) // Credentials(username=a, password=b)
println(creds == Credentials("a", "b")) // true
2. Problems Kotlin solves _57
3. Solution: Kotlin data classes
—
// Kotlin
data class Credentials(val username: String, val password: String) {
override fun toString(): String {
return "$username/$password"
}
}
println(Credentials("one", "two")) // one/two
2. Problems Kotlin solves _58
3. Data classes: Java & Groovy
—
• Java (Lombok https://projectlombok.org/)
• Groovy (@groovy.transform.Canonical)
2. Problems Kotlin solves _59
4. Problem: steps in Allure report
—
// Java
driver.findElement("button").click();
2. Problems Kotlin solves _60
4. Problem: steps in Allure report
—
// Java
@Step("Click the button")
public void clickButton() {
driver.findElement("button").click();
}
clickButton();
2. Problems Kotlin solves _61
4. Solution: steps in Allure report
—
// Java 8
@Step("{0}")
public void step(String title, Runnable code) {
code.run();
}
step("Click the button", () -> {
driver.findElement("button").click();
});
2. Problems Kotlin solves _62
4. Solution: steps in Allure report
—
// Kotlin
@Step("{0}")
fun step(title: String, code: () -> Any) = code()
step("Click the button") {
driver.findElement("button").click()
}
2. Problems Kotlin solves _63
4. Solution: just compare
—
// Java 8
step("Click the button", () -> {
// your code here
});
// Kotlin
step("Click the button") {
// your code here
}
2. Problems Kotlin solves _64
4. Steps in Allure report: Java & Groovy
—
• Java 7
• Java 8
• Groovy
2. Problems Kotlin solves _65
5. Problem: checked exceptions
—
// Java
URLDecoder.decode(param, "UTF-8");
2. Problems Kotlin solves _66
// Java
URLDecoder.decode(param, "UTF-8");
// Kotlin
URLDecoder.decode(param, "UTF-8")
5. Solution: no checked exceptions
—
2. Problems Kotlin solves _67
5. Checked exceptions: Java & Groovy
—
• Java
• Groovy
2. Problems Kotlin solves _68
6. Problem: unchecked cast
—
// Java
Object results
= ((JavascriptExecutor) driver).executeScript("...");
2. Problems Kotlin solves _69
// Java
Object results
= ((JavascriptExecutor) driver).executeScript("...");
if (results instanceof List) {
List<String> list = ((List<Object>) results)
.stream()
.filter(String.class::isInstance)
.map(String.class::cast)
.collect(toList());
}
6. Problem: unchecked cast
—
2. Problems Kotlin solves _70
// Java
Object results
= ((JavascriptExecutor) driver).executeScript("...");
if (results instanceof List) {
List<String> list = ((List<Object>) results)
}
6. Problem: unchecked cast
—
2. Problems Kotlin solves _71
// Kotlin
val results
= (driver as JavascriptExecutor).executeScript("...")
if (results is List<*>) {
val list = results.filterIsInstance<String>()
}
6. Solution: Kotlin smart cast
—
2. Problems Kotlin solves _72
// Kotlin
val results
= (driver as JavascriptExecutor).executeScript("...")
if (results is List<*>) {
val list = results.filterIsInstance<String>()
}
6. Solution: Kotlin smart cast
—
2. Problems Kotlin solves _73
6. Unchecked cast: Java & Groovy
—
• Java
• Groovy
2. Problems Kotlin solves _74
7. Problem: Java is verbose
—
2. Problems Kotlin solves _75
7. Solution: Kotlin syntactic sugar
—
// Java
actualText.equals(expectedText)
// Kotlin
actualText == expectedText
2. Problems Kotlin solves _76
7. Solution: String templates
—
// Java
String s = "date: " + date + " and author: " + USER.getName();
String s =
format("date: %s and author: %s", date, USER.getName());
// Kotlin
val s = "date: $date and author: ${USER.name}"
2. Problems Kotlin solves _77
7. Solution: ranges
—
// Java
for (int i = 0; i <= 10; i += 2)
// Kotlin
for (i in 0..10 step 2)
2. Problems Kotlin solves _78
7. Solution: Kotlin rich standard library
—
// Java
!list.isEmpty()
// Kotlin
list.isNotEmpty()
2. Problems Kotlin solves _79
7. Solution: Kotlin type inference
—
// Java
final int i = 0;
final String s = "abc";
final List<String> list = new ArrayList<>();
// Kotlin
val i = 0
val s = "abc"
val list = listOf("a", "b", "c")
2. Problems Kotlin solves _80
7. Verbosity: Java & Groovy
—
• Java
• Groovy
2. Problems Kotlin solves _81
8. Problem: java.lang.NullPointerException
—
2. Problems Kotlin solves _82
8. Solution: Null safety
—
var username: String
username = null // compilation error
2. Problems Kotlin solves _83
8. Null safety
—
var username: String
username = null // compilation error
var username: String?
username = null // ok
2. Problems Kotlin solves _84
8. Null safety
—
var username: String // non-nullable String
username = null
var username: String? // nullable String
username = null
2. Problems Kotlin solves _85
8. Null safety: safe call
—
var username: String? = "Vasya"
var count = username.length // compilation error
2. Problems Kotlin solves _86
8. Null safety: safe call
—
var username: String? = "Vasya"
var count = username?.length // ok, count is 5
username = null
var count = username?.length // ok, count is null
2. Problems Kotlin solves _87
8. Null safety: Elvis operator
—
input.sendKeys(username ?: "Guest")
var images = findAllImagesOnPage()
?: throw AssertionError("No images")
2. Problems Kotlin solves _88
?:
8. Null safety: Java & Groovy
—
• Null safety: Java (Optional<T> in Java8), Groovy
• Safe call: Java, Groovy
• Elvis operator: Java, Groovy
2. Problems Kotlin solves _89
Java vs Groovy vs Kotlin
—
2. Problems Kotlin solves _90
1 2 3 4 5 6 7 8
Java	7 – – – – – – – –
Java	8 ± – – + – – – –
Groovy + ± + + + – + –
Kotlin + + + + + + + +
Why not Groovy?
—
• Not statically typed: runtime bugs
• Not statically typed: performance
• Not statically typed: IDE support
• No null safety
2. Problems Kotlin solves _91
What’s going on here
—
• What is Kotlin?
• Problems Kotlin solves
• Demo
Excuse me, sir, do you have a moment to talk about tests in Kotlin? _92
Example test project in Kotlin
—
• JUnit http://junit.org/junit4/
• Html Elements https://github.com/yandex-qatools/htmlelements
• Allure Framework https://github.com/allure-framework/
• Gradle https://gradle.org/
• gradle-docker-plugin https://github.com/bmuschko/gradle-docker-plugin
3. Demo _93
https://github.com/leonsabr/seleniumcamp-kotlin-demo
—
3. Demo _94
• Kotlin + { Gradle, JUnit, Selenium, Html Elements, Allure } = OK
https://github.com/leonsabr/seleniumcamp-kotlin-demo
—
3. Demo _95
• Kotlin + { Gradle, JUnit, Selenium, Html Elements, Allure }
• Java interoperability
https://github.com/leonsabr/seleniumcamp-kotlin-demo
—
3. Demo _96
java kotlin ∆
main 670 434 35,2%
test 92 84 8,7%
total 762 518 32%
• Kotlin + { Gradle, JUnit, Selenium, Html Elements, Allure }
• Java interoperability
• Conciseness (lines of code)
Useful links
—
• Reference http://kotlinlang.org/docs/reference/
• List of Kotlin resources https://kotlin.link/
• Try Kotlin online http://try.kotl.in/
• Slack https://kotlinlang.slack.com/
_97
Thank you
for your attention
—
jetbrains.com
leonid.rudenko@jetbrains.com
@leonsabr

More Related Content

PDF
Java → kotlin: Tests Made Simple
PPTX
Kotlin – the future of android
PPTX
01 Java Language And OOP Part I LAB
PPTX
06 Java Language And OOP Part VI
PDF
Clojure for Java developers
PDF
Kotlin - Better Java
PDF
Clojure, Plain and Simple
PDF
Kotlin: Why Do You Care?
Java → kotlin: Tests Made Simple
Kotlin – the future of android
01 Java Language And OOP Part I LAB
06 Java Language And OOP Part VI
Clojure for Java developers
Kotlin - Better Java
Clojure, Plain and Simple
Kotlin: Why Do You Care?

What's hot (20)

PDF
Kotlin: a better Java
ODP
Getting started with Clojure
PDF
Kotlin intro
PPTX
Kotlin coroutines and spring framework
PDF
Kotlin @ Coupang Backend 2017
PDF
Clojure made-simple - John Stevenson
PDF
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
PDF
Kotlin Slides from Devoxx 2011
PPT
JDK1.6
KEY
Clojure Intro
PPTX
K is for Kotlin
PDF
Clojure for Java developers - Stockholm
PDF
4java Basic Syntax
PPTX
Exploring Kotlin
PPTX
PDF
Kotlin: Challenges in JVM language design
PPTX
02 Java Language And OOP Part II LAB
PDF
Java7 New Features and Code Examples
PPTX
Kotlin: a better Java
Getting started with Clojure
Kotlin intro
Kotlin coroutines and spring framework
Kotlin @ Coupang Backend 2017
Clojure made-simple - John Stevenson
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
Kotlin Slides from Devoxx 2011
JDK1.6
Clojure Intro
K is for Kotlin
Clojure for Java developers - Stockholm
4java Basic Syntax
Exploring Kotlin
Kotlin: Challenges in JVM language design
02 Java Language And OOP Part II LAB
Java7 New Features and Code Examples
Ad

Viewers also liked (20)

PPTX
How does Java 8 exert hidden power on Test Automation?
PPTX
5 top pain points of test automation
PDF
Better Bullshit Driven Development [SeleniumCamp 2017]
PPTX
Design patterns in test automation
PDF
Test trend analysis: Towards robust reliable and timely tests
PDF
WixAutomation - Test State Pattern - Selenium Camp 2017
PPTX
Roman iovlev. Test UI with JDI - Selenium camp
ODP
Fabulous Tests on Spock and Groovy
PPTX
Test Automation Architecture in Microservices
PPTX
Grading the Quality of Selenium Tests
PPTX
Roman iovlev battle - JDI vs Selenide - Selenium Camp
PPTX
Advanced Automated Visual Testing
PPTX
SoapUI one key to all doors
PPTX
Colorful world-of-visual-automation-testing-latest
PPTX
Protractor framework – how to make stable e2e tests for Angular applications
PPTX
Testing Metrics - Making your tests visible
PDF
End-to-End Test Automation for Both Horizontal and Vertical Scale
PDF
Introduction to Kotlin JVM language
PPTX
Selenide
PDF
Kotlin на практике
How does Java 8 exert hidden power on Test Automation?
5 top pain points of test automation
Better Bullshit Driven Development [SeleniumCamp 2017]
Design patterns in test automation
Test trend analysis: Towards robust reliable and timely tests
WixAutomation - Test State Pattern - Selenium Camp 2017
Roman iovlev. Test UI with JDI - Selenium camp
Fabulous Tests on Spock and Groovy
Test Automation Architecture in Microservices
Grading the Quality of Selenium Tests
Roman iovlev battle - JDI vs Selenide - Selenium Camp
Advanced Automated Visual Testing
SoapUI one key to all doors
Colorful world-of-visual-automation-testing-latest
Protractor framework – how to make stable e2e tests for Angular applications
Testing Metrics - Making your tests visible
End-to-End Test Automation for Both Horizontal and Vertical Scale
Introduction to Kotlin JVM language
Selenide
Kotlin на практике
Ad

Similar to Excuse me, sir, do you have a moment to talk about tests in Kotlin (20)

PDF
A quick and fast intro to Kotlin
PDF
A short introduction to the Kotlin language for Java developers
PPTX
Introduction to Kotlin Language and its application to Android platform
PDF
Little Helpers for Android Development with Kotlin
PPTX
Intro to kotlin 2018
PDF
Is this Swift for Android? A short introduction to the Kotlin language
PDF
Having Fun with Kotlin Android - DILo Surabaya
PDF
Intro to Kotlin
PDF
Kotlin, smarter development for the jvm
PDF
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
PDF
Kotlin 1.2: Sharing code between platforms
PDF
Kotlin @ Devoxx 2011
PPTX
Kotlin
PDF
Kotlin for Android Developers - 1
PDF
JavaCro'14 - Is there Kotlin after Java 8 – Ivan Turčinović and Igor Buzatović
PDF
Be More Productive with Kotlin
PDF
9054799 dzone-refcard267-kotlin
PDF
Kotlin: forse è la volta buona (Trento)
PDF
What’s new in Kotlin?
PDF
A quick and fast intro to Kotlin
A short introduction to the Kotlin language for Java developers
Introduction to Kotlin Language and its application to Android platform
Little Helpers for Android Development with Kotlin
Intro to kotlin 2018
Is this Swift for Android? A short introduction to the Kotlin language
Having Fun with Kotlin Android - DILo Surabaya
Intro to Kotlin
Kotlin, smarter development for the jvm
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
Kotlin 1.2: Sharing code between platforms
Kotlin @ Devoxx 2011
Kotlin
Kotlin for Android Developers - 1
JavaCro'14 - Is there Kotlin after Java 8 – Ivan Turčinović and Igor Buzatović
Be More Productive with Kotlin
9054799 dzone-refcard267-kotlin
Kotlin: forse è la volta buona (Trento)
What’s new in Kotlin?

Recently uploaded (20)

PDF
System and Network Administraation Chapter 3
PPTX
history of c programming in notes for students .pptx
PDF
Digital Strategies for Manufacturing Companies
PPTX
Transform Your Business with a Software ERP System
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PPTX
ai tools demonstartion for schools and inter college
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PPTX
L1 - Introduction to python Backend.pptx
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Nekopoi APK 2025 free lastest update
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
System and Network Administraation Chapter 3
history of c programming in notes for students .pptx
Digital Strategies for Manufacturing Companies
Transform Your Business with a Software ERP System
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
ai tools demonstartion for schools and inter college
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
Softaken Excel to vCard Converter Software.pdf
wealthsignaloriginal-com-DS-text-... (1).pdf
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
L1 - Introduction to python Backend.pptx
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Which alternative to Crystal Reports is best for small or large businesses.pdf
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
CHAPTER 2 - PM Management and IT Context
Nekopoi APK 2025 free lastest update
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus

Excuse me, sir, do you have a moment to talk about tests in Kotlin

  • 1. Excuse me, sir, do you have a moment to talk about tests in Kotlin? — Leonid Rudenko
  • 4. Why? — Selenium Camp 2016 #4 Make Your Automation ier _4
  • 5. What’s going on here — • What is Kotlin? • Problems Kotlin solves • Demo Excuse me, sir, do you have a moment to talk about tests in Kotlin? _5
  • 6. What’s going on here — • What is Kotlin? • Problems Kotlin solves • Demo Excuse me, sir, do you have a moment to talk about tests in Kotlin? _6
  • 7. Kotlin is... — • JVM language from JetBrains – Java 6+ 1. What is Kotlin? _7
  • 8. Kotlin is... — • JVM language • Statically typed 1. What is Kotlin? _8
  • 9. Kotlin is... — • JVM language • Statically typed • Multi-paradigm – OOP & functional 1. What is Kotlin? _9
  • 10. Kotlin is... — • JVM language • Statically typed • Multi-paradigm • Pragmatic 1. What is Kotlin? _10
  • 11. Kotlin is... — • JVM language • Statically typed • Multi-paradigm • Pragmatic • Democratic 1. What is Kotlin? _11
  • 12. Kotlin is... — • JVM language • Statically typed • Multi-paradigm • Pragmatic • Democratic • Safe 1. What is Kotlin? _12
  • 13. Kotlin is... — • JVM language • Statically typed • Multi-paradigm • Pragmatic • Democratic • Safe • Concise 1. What is Kotlin? _13 Brevity is the sister of talent. - Anton Chekhov -
  • 14. Kotlin is... — • JVM language • Statically typed • Multi-paradigm • Pragmatic • Democratic • Safe • Concise • Interoperable 1. What is Kotlin? _14
  • 15. Kotlin is... — • JVM language • Statically typed • Multi-paradigm • Pragmatic • Democratic • Safe • Concise • Interoperable 1. What is Kotlin? _15
  • 16. Kotlin 1.0 — • 15 Feb 2016 – backward compatibility 1. What is Kotlin? _16
  • 17. Kotlin 1.0 — • 15 Feb 2016 • kotlinc, Intellij IDEA (plugin), Eclipse (plugin), NetBeans (plugin) 1. What is Kotlin? _17
  • 18. Kotlin 1.0 — • 15 Feb 2016 • kotlinc, Intellij IDEA (plugin), Eclipse (plugin), NetBeans (plugin) • Open source https://github.com/jetbrains/kotlin 1. What is Kotlin? _18
  • 19. 1. What is Kotlin? _19
  • 20. _20
  • 21. Google Trends: Kotlin 1y — 1. What is Kotlin? _21
  • 22. Google Trends: Kotlin vs Groovy 1y — 1. What is Kotlin? _22
  • 23. Where Kotlin is used — • JetBrains products 1. What is Kotlin? _23
  • 24. Where Kotlin is used — • JetBrains products • Android 1. What is Kotlin? _24
  • 25. Where Kotlin is used — • JetBrains products • Android • Server & Desktop 1. What is Kotlin? _25
  • 26. Where Kotlin is used — • JetBrains products • Android • Server & Desktop • Gradle 3.0 https://github.com/gradle/gradle-script-kotlin 1. What is Kotlin? _26
  • 27. Where Kotlin is used — • JetBrains products • Android • Server & Desktop • Gradle 3.0 • (Web) Test Automation 1. What is Kotlin? _27
  • 28. Test Automation: why Kotlin? — • Syntax similar to Java 1. What is Kotlin? _28
  • 29. Test Automation: why Kotlin? — • Syntax similar to Java • Clean test code Conciseness Easy to read == easy to understand Collective code ownership, effective code review 1. What is Kotlin? _29
  • 30. Test Automation: why Kotlin? — • Syntax similar to Java • Clean test code Conciseness Easy to read == easy to understand Collective code ownership, effective code review • Safe test code 1. What is Kotlin? _30
  • 31. What’s going on here — • What is Kotlin? • Problems Kotlin solves • Demo Excuse me, sir, do you have a moment to talk about tests in Kotlin? _31
  • 32. Kotlin features — • Extension functions • Data classes • Lambda functions • Smart cast • Type inference • Null safety 2. Problems Kotlin solves _32
  • 33. 1. Problem: Maps and Lists in Java — // Java Map<Integer, Credentials> users = new HashMap<>(); users.put(1, new Credentials("vasya", "123456")); users.put(2, new Credentials("johny", "qwerty")); users.put(3, new Credentials("admin", "admin")); List<Integer> responseCodes = new ArrayList<>(); responseCodes.add(200); responseCodes.add(302); 2. Problems Kotlin solves _33
  • 34. 1. Solution: Kotlin collections — // Kotlin val users = mapOf( 1 to Credentials("vasya", "123456"), 2 to Credentials("johny", "qwerty"), 3 to Credentials("admin", "admin")) val responseCodes = listOf(200, 302) 2. Problems Kotlin solves _34
  • 35. 1. Collections: Map — // Kotlin val users = mapOf( 1 to Credentials("vasya", "123456"), 2 to Credentials("johny", "qwerty"), 3 to Credentials("admin", "admin")) Map<Integer, Credentials> new users.put(4, Credentials("...", "...")) 2. Problems Kotlin solves _35
  • 36. 1. Collections: Traversing a map — // Java for (Map.Entry<Integer, Credentials> pair : users.entrySet()) { System.out.println(pair.getKey() + "->" + pair.getValue()); } // Kotlin for ((id, creds) in users) { println("$id->$creds") } 2. Problems Kotlin solves _36
  • 37. 1. Collections: forEach, filters, sorting... — // Kotlin val link = driver.findElements("a").firstOrNull { it.text == "Selenium Camp" } 2. Problems Kotlin solves _37
  • 38. 1. Collections: Java & Groovy — • Java 7 • Java 8 (Stream API) • Groovy 2. Problems Kotlin solves _38
  • 39. 1. Collections: forEach, filters, sorting... — 2. Problems Kotlin solves _39 // Kotlin val link = driver.findElements("a").firstOrNull { it.text == "Selenium Camp" }
  • 40. 2. Problem: framework can’t do what you need it to do — // Java public static List<WebElement> findElements(WebDriver driver, String selector) { return driver.findElements(By.cssSelector(selector)); } findElements(driver, "a"); 2. Problems Kotlin solves _40
  • 41. 2. Problem: framework can’t do what you need it to do — 2. Problems Kotlin solves _41
  • 42. 2. Solution: Extension functions — // Kotlin fun WebDriver.findElements(selector: String): List<WebElement>{ return this.findElements(By.cssSelector(selector)) } driver.findElements("a") 2. Problems Kotlin solves _42
  • 43. 2. Extension functions — // Kotlin fun WebDriver.findElements(selector: String): List<WebElement>{ return this.findElements(By.cssSelector(selector)) } driver.findElements("a") 2. Problems Kotlin solves _43
  • 44. 2. Extension functions — // Kotlin fun WebDriver.findElements(selector: String): List<WebElement>{ return this.findElements(By.cssSelector(selector)) } driver.findElements("a") 2. Problems Kotlin solves _44
  • 45. 2. Extension functions — // Kotlin fun WebDriver.findElements(selector: String): List<WebElement>{ return this.findElements(By.cssSelector(selector)) } driver.findElements("a") 2. Problems Kotlin solves _45
  • 46. 2. Extension functions: Java & Groovy — • Java • Groovy (Extension Modules) 2. Problems Kotlin solves _46
  • 47. 3. Problem: small classes are not small — // Java public class Credentials { private final String username; private final String password; } 2. Problems Kotlin solves _47
  • 48. 3. Problem: small classes are not small — // Java public class Credentials { private final String username; private final String password; public Credentials(String username, String password) { this.username = username; this.password = password; } } 2. Problems Kotlin solves _48
  • 49. 3. Problem: small classes are not small — // Java public class Credentials { private final String username; private final String password; public Credentials(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public String getPassword() { return password; } } 2. Problems Kotlin solves _49
  • 50. 3. Problem: small classes are not small —// Java public class Credentials { private final String username; private final String password; public Credentials(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public String getPassword() { return password; } @Override public String toString() { return username + '/' + password; } } 2. Problems Kotlin solves _50
  • 51. 3. Problem: small classes are not small —// Java public class Credentials { private final String username; private final String password; public Credentials(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public String getPassword() { return password; } @Override public String toString() { return username + '/' + password; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Credentials that = (Credentials) o; if (username != null ? !username.equals(that.username) : that.username != null) return false; return password != null ? password.equals(that.password) : that.password == null; } @Override public int hashCode() { int result = username != null ? username.hashCode() : 0; return 31 * result + (password != null ? password.hashCode() : 0); } } 2. Problems Kotlin solves _51
  • 52. 3. Problem: 27 lines —// Java public class Credentials { private final String username; private final String password; public Credentials(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public String getPassword() { return password; } @Override public String toString() { return username + '/' + password; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Credentials that = (Credentials) o; if (username != null ? !username.equals(that.username) : that.username != null) return false; return password != null ? password.equals(that.password) : that.password == null; } @Override public int hashCode() { int result = username != null ? username.hashCode() : 0; return 31 * result + (password != null ? password.hashCode() : 0); } } 2. Problems Kotlin solves _52
  • 53. 3. Solution: direct to Kotlin – 18 lines —// Java public class Credentials { private final String username; private final String password; public Credentials(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public String getPassword() { return password; } @Override public String toString() { return username + '/' + password; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Credentials that = (Credentials) o; if (username != null ? !username.equals(that.username) : that.username != null) return false; return password != null ? password.equals(that.password) : that.password == null; } @Override public int hashCode() { int result = username != null ? username.hashCode() : 0; return 31 * result + (password != null ? password.hashCode() : 0); } } 2. Problems Kotlin solves _53 // Kotlin class Credentials { private val username: String private val password: String constructor(username: String, password: String) { this.username = username this.password = password } fun getUsername(): String { return username } fun getPassword(): String { return password } override fun toString() = username + '/' + password override fun equals(other: Any?): Boolean { if (this === other) return true if (other?.javaClass != javaClass) return false other as Credentials return username == other.username && password == other.password } override fun hashCode() = 31 * username.hashCode() + password.hashCode() }
  • 54. 3. Solution: remove getters – 16 lines —// Kotlin class Credentials { val username: String val password: String constructor(username: String, password: String) { this.username = username this.password = password } //fun getUsername(): String { return username } //fun getPassword(): String { return password } override fun toString() = username + '/' + password override fun equals(other: Any?): Boolean { if (this === other) return true if (other?.javaClass != javaClass) return false other as Credentials return username == other.username && password == other.password } override fun hashCode() = 31 * username.hashCode() + password.hashCode() } 2. Problems Kotlin solves _54
  • 55. 3. Solution: primary constructor – 10 lines —// Kotlin class Credentials(val username: String, val password: String) { //val username: String //val password: String //constructor(username: String, password: String) { // this.username = username // this.password = password //} override fun toString() = username + '/' + password override fun equals(other: Any?): Boolean { if (this === other) return true if (other?.javaClass != javaClass) return false other as Credentials return username == other.username && password == other.password } override fun hashCode() = 31 * username.hashCode() + password.hashCode() } 2. Problems Kotlin solves _55
  • 56. 3. Solution: data class – 1 line — // Kotlin data class Credentials(val username: String, val password: String) { //override fun toString() = username + '/' + password //override fun equals(other: Any?): Boolean { // if (this === other) return true // if (other?.javaClass != javaClass) return false // other as Credentials // return username == other.username && password == other.password //} //override fun hashCode() = 31 * username.hashCode() + password.hashCode() } 2. Problems Kotlin solves _56
  • 57. 3. Solution: Kotlin data classes — // Kotlin data class Credentials(val username: String, val password: String) val creds = Credentials("a", "b") println(creds.username) // a creds.username = "you can't do that" println(creds) // Credentials(username=a, password=b) println(creds == Credentials("a", "b")) // true 2. Problems Kotlin solves _57
  • 58. 3. Solution: Kotlin data classes — // Kotlin data class Credentials(val username: String, val password: String) { override fun toString(): String { return "$username/$password" } } println(Credentials("one", "two")) // one/two 2. Problems Kotlin solves _58
  • 59. 3. Data classes: Java & Groovy — • Java (Lombok https://projectlombok.org/) • Groovy (@groovy.transform.Canonical) 2. Problems Kotlin solves _59
  • 60. 4. Problem: steps in Allure report — // Java driver.findElement("button").click(); 2. Problems Kotlin solves _60
  • 61. 4. Problem: steps in Allure report — // Java @Step("Click the button") public void clickButton() { driver.findElement("button").click(); } clickButton(); 2. Problems Kotlin solves _61
  • 62. 4. Solution: steps in Allure report — // Java 8 @Step("{0}") public void step(String title, Runnable code) { code.run(); } step("Click the button", () -> { driver.findElement("button").click(); }); 2. Problems Kotlin solves _62
  • 63. 4. Solution: steps in Allure report — // Kotlin @Step("{0}") fun step(title: String, code: () -> Any) = code() step("Click the button") { driver.findElement("button").click() } 2. Problems Kotlin solves _63
  • 64. 4. Solution: just compare — // Java 8 step("Click the button", () -> { // your code here }); // Kotlin step("Click the button") { // your code here } 2. Problems Kotlin solves _64
  • 65. 4. Steps in Allure report: Java & Groovy — • Java 7 • Java 8 • Groovy 2. Problems Kotlin solves _65
  • 66. 5. Problem: checked exceptions — // Java URLDecoder.decode(param, "UTF-8"); 2. Problems Kotlin solves _66
  • 67. // Java URLDecoder.decode(param, "UTF-8"); // Kotlin URLDecoder.decode(param, "UTF-8") 5. Solution: no checked exceptions — 2. Problems Kotlin solves _67
  • 68. 5. Checked exceptions: Java & Groovy — • Java • Groovy 2. Problems Kotlin solves _68
  • 69. 6. Problem: unchecked cast — // Java Object results = ((JavascriptExecutor) driver).executeScript("..."); 2. Problems Kotlin solves _69
  • 70. // Java Object results = ((JavascriptExecutor) driver).executeScript("..."); if (results instanceof List) { List<String> list = ((List<Object>) results) .stream() .filter(String.class::isInstance) .map(String.class::cast) .collect(toList()); } 6. Problem: unchecked cast — 2. Problems Kotlin solves _70
  • 71. // Java Object results = ((JavascriptExecutor) driver).executeScript("..."); if (results instanceof List) { List<String> list = ((List<Object>) results) } 6. Problem: unchecked cast — 2. Problems Kotlin solves _71
  • 72. // Kotlin val results = (driver as JavascriptExecutor).executeScript("...") if (results is List<*>) { val list = results.filterIsInstance<String>() } 6. Solution: Kotlin smart cast — 2. Problems Kotlin solves _72
  • 73. // Kotlin val results = (driver as JavascriptExecutor).executeScript("...") if (results is List<*>) { val list = results.filterIsInstance<String>() } 6. Solution: Kotlin smart cast — 2. Problems Kotlin solves _73
  • 74. 6. Unchecked cast: Java & Groovy — • Java • Groovy 2. Problems Kotlin solves _74
  • 75. 7. Problem: Java is verbose — 2. Problems Kotlin solves _75
  • 76. 7. Solution: Kotlin syntactic sugar — // Java actualText.equals(expectedText) // Kotlin actualText == expectedText 2. Problems Kotlin solves _76
  • 77. 7. Solution: String templates — // Java String s = "date: " + date + " and author: " + USER.getName(); String s = format("date: %s and author: %s", date, USER.getName()); // Kotlin val s = "date: $date and author: ${USER.name}" 2. Problems Kotlin solves _77
  • 78. 7. Solution: ranges — // Java for (int i = 0; i <= 10; i += 2) // Kotlin for (i in 0..10 step 2) 2. Problems Kotlin solves _78
  • 79. 7. Solution: Kotlin rich standard library — // Java !list.isEmpty() // Kotlin list.isNotEmpty() 2. Problems Kotlin solves _79
  • 80. 7. Solution: Kotlin type inference — // Java final int i = 0; final String s = "abc"; final List<String> list = new ArrayList<>(); // Kotlin val i = 0 val s = "abc" val list = listOf("a", "b", "c") 2. Problems Kotlin solves _80
  • 81. 7. Verbosity: Java & Groovy — • Java • Groovy 2. Problems Kotlin solves _81
  • 83. 8. Solution: Null safety — var username: String username = null // compilation error 2. Problems Kotlin solves _83
  • 84. 8. Null safety — var username: String username = null // compilation error var username: String? username = null // ok 2. Problems Kotlin solves _84
  • 85. 8. Null safety — var username: String // non-nullable String username = null var username: String? // nullable String username = null 2. Problems Kotlin solves _85
  • 86. 8. Null safety: safe call — var username: String? = "Vasya" var count = username.length // compilation error 2. Problems Kotlin solves _86
  • 87. 8. Null safety: safe call — var username: String? = "Vasya" var count = username?.length // ok, count is 5 username = null var count = username?.length // ok, count is null 2. Problems Kotlin solves _87
  • 88. 8. Null safety: Elvis operator — input.sendKeys(username ?: "Guest") var images = findAllImagesOnPage() ?: throw AssertionError("No images") 2. Problems Kotlin solves _88 ?:
  • 89. 8. Null safety: Java & Groovy — • Null safety: Java (Optional<T> in Java8), Groovy • Safe call: Java, Groovy • Elvis operator: Java, Groovy 2. Problems Kotlin solves _89
  • 90. Java vs Groovy vs Kotlin — 2. Problems Kotlin solves _90 1 2 3 4 5 6 7 8 Java 7 – – – – – – – – Java 8 ± – – + – – – – Groovy + ± + + + – + – Kotlin + + + + + + + +
  • 91. Why not Groovy? — • Not statically typed: runtime bugs • Not statically typed: performance • Not statically typed: IDE support • No null safety 2. Problems Kotlin solves _91
  • 92. What’s going on here — • What is Kotlin? • Problems Kotlin solves • Demo Excuse me, sir, do you have a moment to talk about tests in Kotlin? _92
  • 93. Example test project in Kotlin — • JUnit http://junit.org/junit4/ • Html Elements https://github.com/yandex-qatools/htmlelements • Allure Framework https://github.com/allure-framework/ • Gradle https://gradle.org/ • gradle-docker-plugin https://github.com/bmuschko/gradle-docker-plugin 3. Demo _93
  • 94. https://github.com/leonsabr/seleniumcamp-kotlin-demo — 3. Demo _94 • Kotlin + { Gradle, JUnit, Selenium, Html Elements, Allure } = OK
  • 95. https://github.com/leonsabr/seleniumcamp-kotlin-demo — 3. Demo _95 • Kotlin + { Gradle, JUnit, Selenium, Html Elements, Allure } • Java interoperability
  • 96. https://github.com/leonsabr/seleniumcamp-kotlin-demo — 3. Demo _96 java kotlin ∆ main 670 434 35,2% test 92 84 8,7% total 762 518 32% • Kotlin + { Gradle, JUnit, Selenium, Html Elements, Allure } • Java interoperability • Conciseness (lines of code)
  • 97. Useful links — • Reference http://kotlinlang.org/docs/reference/ • List of Kotlin resources https://kotlin.link/ • Try Kotlin online http://try.kotl.in/ • Slack https://kotlinlang.slack.com/ _97
  • 98. Thank you for your attention — jetbrains.com leonid.rudenko@jetbrains.com @leonsabr