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

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

  • 1.
    Excuse me, sir, doyou have a moment to talk about tests in Kotlin? — Leonid Rudenko
  • 2.
  • 3.
  • 4.
    Why? — Selenium Camp 2016 #4Make Your Automation ier _4
  • 5.
    What’s going onhere — • 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 onhere — • 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... — • JVMlanguage from JetBrains – Java 6+ 1. What is Kotlin? _7
  • 8.
    Kotlin is... — • JVMlanguage • Statically typed 1. What is Kotlin? _8
  • 9.
    Kotlin is... — • JVMlanguage • Statically typed • Multi-paradigm – OOP & functional 1. What is Kotlin? _9
  • 10.
    Kotlin is... — • JVMlanguage • Statically typed • Multi-paradigm • Pragmatic 1. What is Kotlin? _10
  • 11.
    Kotlin is... — • JVMlanguage • Statically typed • Multi-paradigm • Pragmatic • Democratic 1. What is Kotlin? _11
  • 12.
    Kotlin is... — • JVMlanguage • Statically typed • Multi-paradigm • Pragmatic • Democratic • Safe 1. What is Kotlin? _12
  • 13.
    Kotlin is... — • JVMlanguage • Statically typed • Multi-paradigm • Pragmatic • Democratic • Safe • Concise 1. What is Kotlin? _13 Brevity is the sister of talent. - Anton Chekhov -
  • 14.
    Kotlin is... — • JVMlanguage • Statically typed • Multi-paradigm • Pragmatic • Democratic • Safe • Concise • Interoperable 1. What is Kotlin? _14
  • 15.
    Kotlin is... — • JVMlanguage • Statically typed • Multi-paradigm • Pragmatic • Democratic • Safe • Concise • Interoperable 1. What is Kotlin? _15
  • 16.
    Kotlin 1.0 — • 15Feb 2016 – backward compatibility 1. What is Kotlin? _16
  • 17.
    Kotlin 1.0 — • 15Feb 2016 • kotlinc, Intellij IDEA (plugin), Eclipse (plugin), NetBeans (plugin) 1. What is Kotlin? _17
  • 18.
    Kotlin 1.0 — • 15Feb 2016 • kotlinc, Intellij IDEA (plugin), Eclipse (plugin), NetBeans (plugin) • Open source https://github.com/jetbrains/kotlin 1. What is Kotlin? _18
  • 19.
    1. What isKotlin? _19
  • 20.
  • 21.
    Google Trends: Kotlin1y — 1. What is Kotlin? _21
  • 22.
    Google Trends: Kotlinvs Groovy 1y — 1. What is Kotlin? _22
  • 23.
    Where Kotlin isused — • JetBrains products 1. What is Kotlin? _23
  • 24.
    Where Kotlin isused — • JetBrains products • Android 1. What is Kotlin? _24
  • 25.
    Where Kotlin isused — • JetBrains products • Android • Server & Desktop 1. What is Kotlin? _25
  • 26.
    Where Kotlin isused — • JetBrains products • Android • Server & Desktop • Gradle 3.0 https://github.com/gradle/gradle-script-kotlin 1. What is Kotlin? _26
  • 27.
    Where Kotlin isused — • JetBrains products • Android • Server & Desktop • Gradle 3.0 • (Web) Test Automation 1. What is Kotlin? _27
  • 28.
    Test Automation: whyKotlin? — • Syntax similar to Java 1. What is Kotlin? _28
  • 29.
    Test Automation: whyKotlin? — • 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: whyKotlin? — • 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 onhere — • 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 — • Extensionfunctions • Data classes • Lambda functions • Smart cast • Type inference • Null safety 2. Problems Kotlin solves _32
  • 33.
    1. Problem: Mapsand 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: Kotlincollections — // 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: Traversinga 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: frameworkcan’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: frameworkcan’t do what you need it to do — 2. Problems Kotlin solves _41
  • 42.
    2. Solution: Extensionfunctions — // 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: smallclasses are not small — // Java public class Credentials { private final String username; private final String password; } 2. Problems Kotlin solves _47
  • 48.
    3. Problem: smallclasses 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: smallclasses 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: smallclasses 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: smallclasses 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: 27lines —// 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: directto 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: removegetters – 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: primaryconstructor – 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: dataclass – 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: Kotlindata 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: Kotlindata 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: stepsin Allure report — // Java driver.findElement("button").click(); 2. Problems Kotlin solves _60
  • 61.
    4. Problem: stepsin Allure report — // Java @Step("Click the button") public void clickButton() { driver.findElement("button").click(); } clickButton(); 2. Problems Kotlin solves _61
  • 62.
    4. Solution: stepsin 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: stepsin 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: justcompare — // 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 inAllure report: Java & Groovy — • Java 7 • Java 8 • Groovy 2. Problems Kotlin solves _65
  • 66.
    5. Problem: checkedexceptions — // 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: uncheckedcast — // 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: Javais verbose — 2. Problems Kotlin solves _75
  • 76.
    7. Solution: Kotlinsyntactic sugar — // Java actualText.equals(expectedText) // Kotlin actualText == expectedText 2. Problems Kotlin solves _76
  • 77.
    7. Solution: Stringtemplates — // 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: Kotlinrich standard library — // Java !list.isEmpty() // Kotlin list.isNotEmpty() 2. Problems Kotlin solves _79
  • 80.
    7. Solution: Kotlintype 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
  • 82.
  • 83.
    8. Solution: Nullsafety — var username: String username = null // compilation error 2. Problems Kotlin solves _83
  • 84.
    8. Null safety — varusername: String username = null // compilation error var username: String? username = null // ok 2. Problems Kotlin solves _84
  • 85.
    8. Null safety — varusername: 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 Groovyvs 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 onhere — • 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 projectin 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 javakotlin ∆ 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 — • Referencehttp://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 yourattention — jetbrains.com leonid.rudenko@jetbrains.com @leonsabr