Excuse me, sir, do you have a moment to talk about tests in Kotlin
Transcript of Excuse me, sir, do you have a moment to talk about tests in Kotlin
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• Statically typed• Multi-paradigm – OOP & functional
1. What is Kotlin? _9
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
Brevityisthesisteroftalent.- AntonChekhov-
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• 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
Where Kotlin is used—
• JetBrains products• Android• Server & Desktop• Gradle3.0 https://github.com/gradle/gradle-script-kotlin
1. What is Kotlin? _26
Where Kotlin is used—
• JetBrains products• Android• Server & Desktop• Gradle3.0• (Web) Test Automation
1. What is Kotlin? _27
Test Automation: why Kotlin?—• Syntax similar to Java
• Clean test codeConcisenessEasy to read == easy to understandCollective code ownership, effective code review
1. What is Kotlin? _29
Test Automation: why Kotlin?—• Syntax similar to Java
• Clean test codeConcisenessEasy to read == easy to understandCollective 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—
// JavaMap<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—
// Kotlinval 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—
// Kotlinval users = mapOf(
1 to Credentials("vasya", "123456"),2 to Credentials("johny", "qwerty"),3 to Credentials("admin", "admin"))
Map<Integer, Credentials>newusers.put(4, Credentials("...", "..."))
2. Problems Kotlin solves _35
1. Collections: Traversing a map—
// Javafor (Map.Entry<Integer, Credentials> pair : users.entrySet()) {
System.out.println(pair.getKey() + "->" + pair.getValue());}
// Kotlinfor ((id, creds) in users) {
println("$id->$creds")}
2. Problems Kotlin solves _36
1. Collections: forEach, filters, sorting...—
// Kotlinval 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
// Kotlinval link = driver.findElements("a").firstOrNull {
it.text == "Selenium Camp"}
2. Problem: framework can’t do what you need it to do—
// Javapublic static List<WebElement> findElements(WebDriver driver, String selector) {
return driver.findElements(By.cssSelector(selector));}
findElements(driver, "a");
2. Problems Kotlin solves _40
2. Solution: Extension functions—
// Kotlinfun WebDriver.findElements(selector: String): List<WebElement>{
return this.findElements(By.cssSelector(selector))}
driver.findElements("a")
2. Problems Kotlin solves _42
2. Extension functions—
// Kotlinfun WebDriver.findElements(selector: String): List<WebElement>{
return this.findElements(By.cssSelector(selector))}
driver.findElements("a")
2. Problems Kotlin solves _43
2. Extension functions—
// Kotlinfun WebDriver.findElements(selector: String): List<WebElement>{
return this.findElements(By.cssSelector(selector))}
driver.findElements("a")
2. Problems Kotlin solves _44
2. Extension functions—
// Kotlinfun 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—// Javapublic class Credentials {
private final String username;private final String password;
}
2. Problems Kotlin solves _47
3. Problem: small classes are not small—// Javapublic 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—// Javapublic 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—// Javapublic 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; }
@Overridepublic String toString() {
return username + '/' + password;}
}
2. Problems Kotlin solves _50
3. Problem: small classes are not small—// Javapublic 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; }
@Overridepublic String toString() {
return username + '/' + password;}
@Overridepublic 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;
}@Overridepublic 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—// Javapublic 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; }
@Overridepublic String toString() {
return username + '/' + password;}
@Overridepublic 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;
}@Overridepublic 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—// Javapublic 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; }
@Overridepublic String toString() {
return username + '/' + password;}
@Overridepublic 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;
}@Overridepublic int hashCode() {
int result = username != null ? username.hashCode() : 0;return 31 * result + (password != null ? password.hashCode() : 0);
}}
2. Problems Kotlin solves _53
// Kotlinclass Credentials {
private val username: Stringprivate val password: String
constructor(username: String, password: String) {this.username = usernamethis.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 trueif (other?.javaClass != javaClass) return falseother as Credentialsreturn username == other.username && password == other.password
}
override fun hashCode() = 31 * username.hashCode() + password.hashCode()
}
3. Solution: remove getters – 16 lines —// Kotlinclass Credentials {val username: Stringval password: String
constructor(username: String, password: String) {this.username = usernamethis.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 trueif (other?.javaClass != javaClass) return falseother as Credentialsreturn 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—// Kotlinclass 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 trueif (other?.javaClass != javaClass) return falseother as Credentialsreturn 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 —// Kotlindata 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—
// Kotlindata class Credentials(val username: String, val password: String)
val creds = Credentials("a", "b")println(creds.username) // acreds.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—
// Kotlindata 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—
// Javadriver.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 8step("Click the button", () -> {
// your code here});
// Kotlinstep("Click the button") {
// your code here}
2. Problems Kotlin solves _64
5. Problem: checked exceptions—
// JavaURLDecoder.decode(param, "UTF-8");
2. Problems Kotlin solves _66
// JavaURLDecoder.decode(param, "UTF-8");
// KotlinURLDecoder.decode(param, "UTF-8")
5. Solution: no checked exceptions—
2. Problems Kotlin solves _67
6. Problem: unchecked cast—
// JavaObject results
= ((JavascriptExecutor) driver).executeScript("...");
2. Problems Kotlin solves _69
// JavaObject 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
// JavaObject results
= ((JavascriptExecutor) driver).executeScript("...");if (results instanceof List) {
List<String> list = ((List<Object>) results)
}
6. Problem: unchecked cast—
2. Problems Kotlin solves _71
// Kotlinval results
= (driver as JavascriptExecutor).executeScript("...")if (results is List<*>) {
val list = results.filterIsInstance<String>() }
6. Solution: Kotlin smart cast—
2. Problems Kotlin solves _72
// Kotlinval results
= (driver as JavascriptExecutor).executeScript("...")if (results is List<*>) {
val list = results.filterIsInstance<String>() }
6. Solution: Kotlin smart cast—
2. Problems Kotlin solves _73
7. Solution: Kotlin syntactic sugar—
// JavaactualText.equals(expectedText)
// KotlinactualText == expectedText
2. Problems Kotlin solves _76
7. Solution: String templates—
// JavaString s = "date: " + date + " and author: " + USER.getName();String s =
format("date: %s and author: %s", date, USER.getName());
// Kotlinval s = "date: $date and author: ${USER.name}"
2. Problems Kotlin solves _77
7. Solution: ranges—
// Javafor (int i = 0; i <= 10; i += 2)
// Kotlinfor (i in 0..10 step 2)
2. Problems Kotlin solves _78
7. Solution: Kotlin rich standard library—
// Java!list.isEmpty()
// Kotlinlist.isNotEmpty()
2. Problems Kotlin solves _79
7. Solution: Kotlin type inference—
// Javafinal int i = 0;final String s = "abc";final List<String> list = new ArrayList<>();
// Kotlinval i = 0val s = "abc"val list = listOf("a", "b", "c")
2. Problems Kotlin solves _80
8. Solution: Null safety—
var username: Stringusername = null // compilation error
2. Problems Kotlin solves _83
8. Null safety—
var username: Stringusername = null // compilation error
var username: String?username = null // ok
2. Problems Kotlin solves _84
8. Null safety—
var username: String // non-nullable Stringusername = null
var username: String? // nullable Stringusername = 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 = nullvar 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
Java7 – – – – – – – –
Java8 ± – – + – – – –
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