How to enter android automation (part 1)

Let's sniff kotlin

Let’s sniff kotlin

There are not many guides on the Internet on how to master native mobile automation. Many refuse this idea, because it is difficult. Therefore, I decided to write a series of articles that, in my opinion, can help in mastering this craft.

First of all, I would like to clarify that we will consider automation on the native framework (Espresso) and add-ons on it (Kaspresso, Ultron), and not these appiums of yours. In my opinion, working with a native tool gives more skills and advantages in the long run (if the framework can be applied to your task), but that’s my IMHO.

Actually, let’s get straight to the point and discuss what you need to do on this path in the first place.

The very base-base you need to master is the kotlin programming language. Why not java? Because there is a more convenient and promising kotlin and most companies on the market have a stack in this language.
Kotlin is built on top of Java, so testers with Java experience will find it easier to learn Kotlin. Many points in learning kotlin will be clearer and easier to follow. But if there is no such knowledge or experience, then this is not a sentence. Everything can be learned with the right approach and motivation.

“Well, here it is, kotlin… There’s a lot of things in there that it’s not clear to learn.” I have heard such statements more than once or twice. Therefore, let’s look at the kotlin core, which, in my opinion, will be sufficient.

  • Variables, constants and their initialization, lazy initialization

  • Conditional statements

  • Cycles

  • Reference types

  • nullable types

  • array

  • Functions

  • Classes, constructors, objects

  • Inheritance

  • keyword this

  • override keyword

  • super keyword

  • getter/setter

  • Access Modifiers

  • data class

  • Nested, Inner classes

  • Extensions

  • Interfaces

  • Abstract classes

  • Anonymous class

  • companion object

  • is, as cast

  • Comparing objects and values

  • Enum class

  • Collections in Kotlin (Mutable, read-only)

  • Set, List, Map, Sequence + their interfaces

  • Working with collections: sorting different types, enumeration

  • Generics

  • Lambda Expressions, Anonymous Functions, Higher Order Functions

  • scope functions

Yes, the list is rather long, but here is everything that is really useful when applying the right approaches to writing automated tests and infrastructure for them. If you really want to understand what is written in the code by your colleagues and programmers, and not copy-paste the code into your tests, then this is your choice.

Let’s have some details about each item:

Variables, constants and their initialization, lazy initialization

Need to know/be able to:

  • difference between val (immutable variable) and var (mutable variable).

  • initializing variables when they are declared or later using a constructor or init method.

  • how to declare and use constants with the const keyword.

  • how to use the lateinit keyword for lazy initialization of variables.

  • deal with initializations through a delegate.

val name: String = "John" // Неизменяемая переменная
var age: Int = 25 // Изменяемая переменная

companion object {
    const val PI = 3.14159 // Константа

lateinit var lazyVariable: String // Отложенная инициализация

val userName: String by lazy { getName() } // Инициализация через делегат

Conditional statements

Need to know/be able to:

  • using the if, else if, and else keywords to execute different blocks of code depending on conditions.

  • using the when statement to match the value of a variable with different options. Note the use of ranges and the in operator in the when clause.

The when statement in Kotlin allows you to match the value of a variable with multiple choices.

val num = 10

if (num > 0) {
    println("Число положительное")
} else if (num < 0) {
    println("Число отрицательное")
} else {
    println("Число равно нулю")

val result = when (num) {
    in 1..10 -> "Число в диапазоне от 1 до 10"
    0 -> "Число равно нулю"
    else -> "Число не входит в указанные диапазоны"


Need to know/be able to:

  • a for loop to iterate over a range or collection.

  • using while and do-while loops to execute a block of code until a certain condition is met. Note the break and continue statements to control the execution of the loop.

for (i in 1..5) {

var i = 1
while (i <= 5) {

i = 1
do {
} while (i <= 5)

Reference types

Need to know/be able to:

  • the difference between reference and primitive data types (Unlike Java (where there are primitive types and reference) – in Kotlin there are no primitive data types, all types are object (reference)).


nullable types

Need to know/be able to:

  • what are nullable types and how they differ from non-null types.

  • consider the safe call (?.) for accessing properties and calling methods on nullable types.

  • note the use of the non-null assertion operator (!!) in cases where you are certain that the value is not null.

var nullableValue: String? = "Nullable"
nullableValue = null // Присваиваем `null` nullable переменной

val length = nullableValue?.length // Безопасный вызов свойства `length`, вернет `null`, если `nullableValue` равно `null`

val uppercaseValue = nullableValue!!.toUpperCase() // Утверждение о ненулевом значении, вызов `toUpperCase()` если `nullableValue` не равно `null`


Need to know/be able to:

  • how to create and initialize arrays of various data types.

  • how to access array elements by index and change element values.

val numbers = arrayOf(1, 2, 3, 4, 5) // Создание массива целых чисел

val names = arrayOf("John", "Mike", "Sarah") // Создание массива строк

val values = intArrayOf(1, 2, 3, 4, 5) // Создание массива целых чисел

println(numbers[0]) // Выводит первый элемент массива (1)

numbers[1] = 10 // Изменение второго элемента массива на 10


Need to know/be able to:

  • how to declare functions using the fun keyword.

  • passing arguments to functions and returning values. Notice the function’s default parameters and named arguments.

fun greet(name: String) {
    println("Привет, $name!")

greet("John") // Выводит "Привет, John!"

fun addNumbers(a: Int, b: Int): Int {
    return a + b

val sum = addNumbers(5, 3) // sum = 8

fun multiplyNumbers(a: Int, b: Int = 2): Int {
    return a * b

val result = multiplyNumbers(4) // result = 8

Classes, constructors, objects

Need to know/be able to:

  • how to declare classes and use constructors.

  • different types of constructors such as primary, secondary, and constructors with default parameters. Note the use of the object keyword to create class objects.

class Person(val name: String, val age: Int) {
    fun introduce() {
        println("Меня зовут $name и мне $age лет")

val person = Person("John", 25)
person.introduce() // Выводит "Меня зовут John и мне 25 лет"

class Car(val brand: String, val model: String) {
    constructor(brand: String) : this(brand, "Unknown")

val car = Car("Toyota")
println(car.model) // Выводит "Unknown"

object MathUtils {
    fun square(number: Int): Int {
        return number * number

val squaredValue = MathUtils.square(5) // squaredValue = 25


Need to know/be able to:

  • how to use inheritance to create subclasses from existing classes.

  • the super keyword to refer to the parent class from a subclass.

open class Animal(val name: String) {
    fun sleep() {
        println("$name спит")

class Cat(name: String) : Animal(name) {
    fun meow() {
        println("$name мяукает")

val cat = Cat("Tom")
cat.sleep() // Выводит "Tom спит"
cat.meow() // Выводит "Tom мяукает"

keyword this

Need to know/be able to:

  • using the this keyword to refer to the current instance of the class.

  • various scenarios for using this, for example, to resolve naming conflicts between class parameters and properties.

class Person(val name: String) {
    fun introduce() {
        println("Меня зовут $name")

    fun changeName(newName: String) { = newName

val person = Person("John")
person.introduce() // Выводит "Меня зовут John"
person.introduce() // Выводит "Меня зовут Mike"

override keyword

Need to know/be able to:

  • using the override keyword to override methods and properties from the parent class.

  • redefinition rules and restrictions.

pen class Shape {
    open fun draw() {
        println("Рисуем фигуру")

class Circle : Shape() {
    override fun draw() {
        println("Рисуем круг")

val shape: Shape = Circle()
shape.draw() // Выводит "Рисуем круг"

super keyword

Need to know/be able to:

  • using the super keyword to access methods and properties of the parent class.

  • how super is used in subclass constructors.

open class Animal(val name: String) {
    open fun makeSound() {
        println("Животное издает звук")

class Dog(name: String) : Animal(name) {
    override fun makeSound() {
        println("Собака лает")

val dog = Dog("Барсик")
// Выводит:
// Животное издает звук
// Собака лает


Need to know/be able to:

  • how to use getters and setters to access class properties.

  • specifics of working with getters and setters, such as computed properties and access modifiers.

class Person {
    var age: Int = 0
        get() = field
        set(value) {
            field = if (value < 0) 0 else value

val person = Person()
person.age = -5
println(person.age) // Выводит "0"

class Circle {
    var radius: Double = 0.0
        set(value) {
            field = if (value < 0) 0.0 else value
        get() = field

val circle = Circle()
circle.radius = -5.0
println(circle.radius) // Выводит "0.0"

Access Modifiers

Need to know/be able to:

  • various access modifiers in Kotlin such as private, protected, internal and public.

  • how access modifiers affect the visibility of classes, properties, and functions.

class Person {
    private var age: Int = 0
    protected var name: String = ""
    internal var address: String = ""
    var phoneNumber: String = ""

val person = Person() = "John" // Доступ к свойству "name" изнутри класса и его подклассов
person.address = "123 Main St" // Доступ к свойству "address" внутри модуля
person.phoneNumber = "123-456-7890" // Доступ к свойству "phoneNumber" везде

class Employee : Person() {
    fun printEmployeeDetails() {
        println(name) // Доступ к свойству "name" унаследованного класса

data class

Need to know/be able to:

  • using data class to create classes for storing data.

  • features provided by the data class, such as automatic generation of the equals(), hashCode(), and toString() methods.

data class Person(val name: String, val age: Int)

val person1 = Person("John", 25)
val person2 = Person("John", 25)

println(person1 == person2) // Выводит "true" (сравнение по содержимому объектов)
println(person1.hashCode()) // Выводит хэш-код объекта
println(person1.toString()) // Выводит строковое представление объекта

Nested, Inner classes

Need to know/be able to:

class Outer {
    private val outerProperty: Int = 10

    class Nested {
        fun accessOuter() {
            // Недоступно: outerProperty

    inner class Inner {
        fun accessOuter() {
            val value = outerProperty

val nested = Outer.Nested()
val inner = Outer().Inner()


Need to know/be able to:

  • how to use extensions to add new features and properties to existing classes.

  • extensions and their limitations.

fun String.isPalindrome(): Boolean {
    return this == this.reversed()

val text = "level"
println(text.isPalindrome()) // Выводит "true"

fun List<Int>.sum(): Int {
    var total = 0
    for (number in this) {
        total += number
    return total

val numbers = listOf(1, 2, 3, 4, 5)
println(numbers.sum()) // Выводит "15"


Need to know/be able to:

  • using interfaces to define contracts that classes must conform to.

  • study the implementation of interfaces by classes and multiple inheritance of interfaces.

interface Drawable {
    fun draw()

class Circle : Drawable {
    override fun draw() {
        println("Рисуем круг")

val circle = Circle()
circle.draw() // Выводит "Рисуем круг"

Abstract classes

Need to know/be able to:

  • the use of abstract classes to define the general structure of classes and the impossibility of creating instances of an abstract class.

  • consider abstract methods and properties that must be implemented in subclasses.

abstract class Shape {
    abstract fun calculateArea(): Double
    abstract fun calculatePerimeter(): Double

class Circle(private val radius: Double) : Shape() {
    override fun calculateArea(): Double {
        return Math.PI * radius * radius

    override fun calculatePerimeter(): Double {
        return 2 * Math.PI * radius

val circle = Circle(5.0)
println(circle.calculateArea()) // Выводит площадь круга
println(circle.calculatePerimeter()) // Выводит периметр круга

Anonymous class

Need to know/be able to:

  • creating anonymous classes without explicitly defining a subclass.

  • using anonymous classes to implement interfaces or extend classes.

interface OnClickListener {
    fun onClick()

val button = Button()
button.setOnClickListener(object : OnClickListener {
    override fun onClick() {
        println("Кнопка нажата")

companion object

Need to know/be able to:

  • using a companion object to create static methods and properties in a class.

  • how companion object can be used to create factory methods or access shared resources.

class MathUtils {
    companion object {
        fun square(number: Int): Int {
            return number * number

val result = MathUtils.square(5)
println(result) // Выводит "25"

is, as cast

Need to know/be able to:

  • using the is operator to check the type of an object and the as operator to explicitly cast.

  • type-safe casting using the as? operator.

fun printLength(value: Any) {
    if (value is String) {

val text: Any = "Hello"
printLength(text) // Выводит длину строки

val number: Any = 42
val doubleNumber = number as? Double
println(doubleNumber) // Выводит "null"

Comparing objects and values

Need to know/be able to:

val number1 = 5
val number2 = 5
val number3: Int? = 5

println(number1 == number2) // Выводит "true" (сравнение значений)
println(number1 === number2) // Выводит "true" (сравнение ссылок)
println(number1 === number3) // Выводит "true" (сравнение ссылок)

Enum class

Need to know/be able to:

  • using enum classes to define a limited set of values.

  • using properties and methods in enum classes.

enum class Color {

val color = Color.GREEN
println(color) // Выводит "GREEN"

enum class Direction(val degrees: Int) {

val direction = Direction.NORTH
println(direction.degrees) // Выводит "0"

Collections in Kotlin (Mutable, read-only)

Need to know/be able to:

  • understand the difference between mutable and read-only collections.

  • Explore the basic collection types such as List, Set, and Map.

// Неизменяемая коллекция
val list: List<String> = listOf("apple", "banana", "orange")
val set: Set<Int> = setOf(1, 2, 3, 4, 5)
val map: Map<String, Int> = mapOf("one" to 1, "two" to 2, "three" to 3)

// Изменяемая коллекция
val mutableList: MutableList<String> = mutableListOf("apple", "banana", "orange")
val mutableSet: MutableSet<Int> = mutableSetOf(1, 2, 3, 4, 5)
val mutableMap: MutableMap<String, Int> = mutableMapOf("one" to 1, "two" to 2, "three" to 3)

// Изменение элементов в изменяемой коллекции
mutableMap["four"] = 4

Set, List, Map, Sequence + their interfaces

Need to know/be able to:

  • basic operations and functions available for Set, List, Map and Sequence.

  • differences between different implementations of these interfaces.

// Set
val set: Set<Int> = setOf(1, 2, 3, 4, 5)
println(set.size) // Выводит размер множества
println(set.contains(3)) // Выводит "true" если множество содержит элемент 3

// List
val list: List<String> = listOf("apple", "banana", "orange")
println(list.size) // Выводит размер списка
println(list.get(1)) // Выводит элемент на позиции 1
println(list.indexOf("banana")) // Выводит индекс элемента "banana"

// Map
val map: Map<String, Int> = mapOf("one" to 1, "two" to 2, "three" to 3)
println(map.size) // Выводит размер словаря
println(map["two"]) // Выводит значение для ключа "two"
println(map.containsKey("three")) // Выводит "true" если словарь содержит ключ "three"

// Sequence
val sequence: Sequence<Int> = sequenceOf(1, 2, 3, 4, 5)
val filteredSequence = sequence.filter { it > 2 }
val transformedSequence = { it * 2 }
val result = transformedSequence.toList()
println(result) // Выводит [6, 8, 10]

Working with collections: sorting different types, enumeration

Need to know/be able to:

  • methods and functions available for sorting collections of different types.

  • iteration and enumeration of elements of collections.

// Сортировка списка чисел
val numbers = listOf(5, 3, 8, 1, 7)
val sortedNumbers = numbers.sorted()
println(sortedNumbers) // Выводит [1, 3, 5, 7, 8]

// Сортировка списка строк
val names = listOf("Alice", "Bob", "Charlie", "David")
val sortedNames = names.sortedBy { it.length }
println(sortedNames) // Выводит [Bob, David, Alice, Charlie]

// Итерация и перебор элементов списка
val fruits = listOf("apple", "banana", "orange")
for (fruit in fruits) {


Need to know/be able to:

  • using generics to create generic classes and functions.

  • type constraints and projection options.

// Универсальный класс
class Box<T>(val value: T)

val intBox = Box(42)
val stringBox = Box("Hello")

// Универсальная функция
fun <T> printValue(value: T) {

printValue(10) // Выводит 10
printValue("Hello") // Выводит "Hello"

Lambda Expressions, Anonymous Functions, Higher Order Functions

Need to know/be able to:

  • use of lambda expressions, anonymous functions and higher order functions.

  • learn about passing functions as arguments and returning them from other functions.

// Лямбда выражение
val sum = { a: Int, b: Int -> a + b }
println(sum(5, 3)) // Выводит 8

// Анонимная функция
val product = fun(a: Int, b: Int): Int {
    return a * b
println(product(5, 3)) // Выводит 15

// Функция высшего порядка
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)

val result = calculate(5, 3) { a, b -> a - b }
println(result) // Выводит 2

scope functions

Need to know/be able to:

  • use of scope-functions (let, run, with, apply, also) for working with objects in a limited scope.

  • differences between different scope-functions and their application in different situations.

// Функция let
val length = "Hello".let { text ->
println(length) // Выводит 5

// Функция run
val result = run {
    val a = 5
    val b = 3
    a + b
println(result) // Выводит 8

// Функция with
val person = Person()
val nameLength = with(person) {
println(nameLength) // Выводит длину имени объекта person

// Функция apply
val person = Person().apply {
    name = "Alice"
    age = 30

// Функция also
val numbers = mutableListOf(1, 2, 3)
val modifiedNumbers = numbers.also { list ->
println(modifiedNumbers) // Выводит [1, 3, 4]

For those who need videos and to chew, I can recommend the resources that I used (not advertising):

Javabegin – here you need to find Kotlin, as part of a huge full-stack developer course. The material is very well recorded, but for a fee.
Stepik – Kotlin – quick start – also a paid course, but it’s worth it.
developer.alexanderklimov – as an additional resource for courses or a resource for self-study. (for free)
Metanit – as additional material, very well described. (for free)
Kotlin language guide – translations of. documentation. (for some, this is the best resource for self-study) (free)
Kotlin in an hour. Theory and practice. – as additional material for those who wrote in java (free)
Kotlin training course from scratch – Kotlin course from scratch (free)

Most importantly, if you take courses, then there will be some practice as you go through the video. If you’re a self-taught student, it’s easier to take easy problems on sites like Leetcode and CodeWars and solve them a little at a time.

This is enough for you to master the topics described above. After passing one of the courses, it will be possible to start mastering the android and the test framework. We will talk about this in the next article.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *