Без хайпа и маркетинга: нужен ли вам Kotlin?

В рамках QAFest 2017 автор блога automation-remarks.com и Lead QA Automation Engineer в Ciklum Сергей Пирогов рассказал, как он докатилися до Kotlin и что из этого вышло. Для читателей DOU, которые не присутствовали на конференции, Сергей изложил этот опыт в авторской статье.

Меня зовут Сергей Пирогов. Уже более пяти лет я занимаюсь вопросами автоматизации тестирования на проектах различного масштаба и сложности. В основном я занимаюсь автоматизацией тестирования с использованием технологий из мира Java.

Kotlin на текущий момент однозначно находится на пике популярности и в тестировании может принести немало пользы. Но не все так просто, в чем вы можете убедиться из этой статьи.

Предыстория: Java, Groovy и другие альтернативы

Java является самым старым и популярным языком на JVM. Отличный язык и инфраструктура. Бесспорный фаворит различных рейтингов среди языков программирования. На Scala мы проектов писать не пробовали из-за излишней сложности, а вот на Groovy писали и достаточно успешно. Этим опытом я делился на конференции Selenium Camp 2016. Увы, Groovy умирает и появление Kotlin его агонию лишь ускоряет.

Откуда взялся этот ваш Kotlin?

Kotlin — достаточно молодой язык, который разрабатывается и спонсируется компанией JetBrains. Из открытых источников можно узнать, что в разработку языка было вложено более $15 млн, а сам язык — это еще один способ популяризовать компанию и еще больше повысить продажи для Idea.

Язык начал набирать популярность после того, как на конференции JavaOne 2015 Hans Dockter, CEO of Gradle, заявил, что Kotlin получает официальную поддержку для написания Gradle билд-скриптов. Тогда Kotlin все еще был в бете, но новость всколыхнула всех неравнодушных. Волна хайпа начала подниматься уже в тот момент. На пике популярности язык оказался в мае этого года на конференции Google I/O, где было объявлено о том, что Kotlin наряду с Java становится официальным языком разработки под платформу Android. Тут-то всех и «лупануло»: весь Twitter был в постах о Kotlin, появилась куча блог-постов с признаниями в любви языку. Представители JetBrains в различных источниках стали заявлять, что Kotlin — это будущее разработки на JVM.

В целом если смотреть на ситуацию здраво, то причины хайпа вполне понятны. Джава развивается слишком медленно. Java 8 появилась аж в 2014 году, Java 9 на момент публикации уже вышла, но в самом языке слишком мало вкусных фишек. Более того, с Java 9 у многих все в момент перестало работать. И тут людям дают язык, наполненный фичами, часть из которых появится только в 10-ке (и то с оговоркой «может быть ...»).

Чем этот ваш Kotlin круче?

Авторы языка признаются, что не пытались придумать что-то кардинально новое. Язык специально задумывался максимально прагматичным и удобным в использовании для разработчиков. Вот небольшой список фишек, которые есть в Kotlin:

C более полным списком можно ознакомиться по ссылке.

И что? Как оно помогает жить?

Null safety — это selling point Kotlin. Проверка на nullable type осуществляется еще во время компиляции.

var a: String = "abc"
a = null // compilation error

var b: String? = "abc"
b = null // ok

Это очень удобно и помогает избежать многих багов.

Extension functions — это фича, которой мне лично очень не хватает в Java. Ниже пример, как с помощью всего пары функций можно улучшить существующий Selenium API.

fun WebDriver.open(url: String) {
    get(url)
}

fun WebDriver.all(cssselector: String): MutableList<WebElement>? {
    return findElements(By.cssSelector(cssselector))
}

fun List<WebElement>.shouldHave(size: Int) {
    assert(this.size == size)
}

По итогу мы можем писать тесты в таком формате:

val driver = ChromeDriver()
driver.open("http://automation-remarks.com")
driver.all(".post").shouldHave(size = 9)

Еще одной фишкой являются функции типа .apply, .with. C их применением можно сделать код более компактным.

ChromeDriver().apply {
        open("http://automation-remarks.com")
        all(".post").shouldHave(size = 9)
}

String template — позволяет удобно форматировать строки. Мы очень часто пользуемся этим в тестах.

fun findCustomerById(id:Long): CustomerEntity{

    val query = """
                SELECT *
                FROM customer
                WHERE id = $id;
                """

    return findOne(CustomerEntity::klass, query)
}

Как видите, SQL запрос не содержит уродливых переносов строк и конкатенаций. Его просто читать, копировать и редактировать.

Reified type — фишка, которая позволяет сделать ваш код очень красивым и лаконичным. Например, мы в тестах часто пользуемся библиотекой Apache DBUtils. С ее применением код получается таким:

val beanHandler = BeanHandler<City>(City::class.java)
val city: City  = QueryRunner().query("SELECT * FROM city", beanHandler)

Но, применив уже знакомые нам extension function и reified type, мы можем сделать так:

inline fun <reified T> QueryRunner.findOne(sql: String): T {
    return BeanHandler(T::class.java).run { query(sql, this) }
}

и получить следующий код:

val city : City = QueryRunner().findOne("SELECT * FROM city")

В этом случае тип, в который конвертируется результат запроса, будет браться из типа объявленной переменной. Это гораздо удобнее, чем Java Generics.

Совместимость с Java

Из официальной документации известно, что Kotlin разрабатывался с оглядкой на максимальную совместимость с Java. Java Interop подается под соусом, что мы можем взять любой код, написанный раньше, и вызвать в Kotlin. Либо же обратно — няшный Kotlin-код вызвать в унылой джавке.

Так ли это на самом деле? Давайте разбираться.

Kotlin vs Rest Assured

Для написания тестов для API мы используем одну из лучших библиотек — Rest Assured. Посмотрим, как она будет работать в Kotlin.

Опа-опа, when зарезервированное слово. Обойти такое ограничение можно, обернув его в такие вот интересные кавычки. Скажу честно, я даже не сразу нашел эти символы на своей клавиатуре :-)

Kotlin + Selenide

Для написания UI тестов мы используем Selenide. Давайте посмотрим на совместимость.

И снова неудача — $ нельзя, val тоже нельзя.

Kotlin + Hamcrest (AssertJ)

Все мы при написании тестов активно используем такие библиотеки, как Hamcrest и AssertJ. Что с совместимостью?

Здесь нас тоже ждут ограничения.

Все через костыли

Когда начинаешь натыкаться на такие ограничения, то напрашивается вполне логичная мысль...

Чиним Kotlin и Rest Assured

На самом деле все предыдущие примеры можно в какой-то степени починить. Смотрим на пример с Rest Assured:

fun RequestSpecification.When(): RequestSpecification {
        return this.`when`()
}

@Test
fun basicPingTest() {
   given()
      .When()
      .get("/garage")
      .then().statusCode(200);
}

Делаем extension function, в который оборачиваем вызов when. Работает? Работает. Да, это костыль, но рабочий.

Чиним Kotlin vs Selenide

В случае с Selenide нам нужно просто обернуть вызовы функций $ и $$, a вместо .val() вызывать .setValue().

fun get(selector: String) : SelenideElement {
     return `$`(selector);
 }
    
 fun all(selector: String) : ElementsCollection {
     return `$$`(selector);
 }

Результат:

@Test fun usingDollarsWithBackticks() {
        get(By.name("q")).setValue("selenide")
        all("#ires .g").shouldHave(size(10))
        get("#ires .g").shouldHave(text("Kotlin"));
 }

Чиним Kotlin + Hamcrest (AssertJ)

Увы, по этому пункту нас ждет разочарование. Если Hamcrest еще как-то совместим с Kotlin, то AssertJ починить не получится из-за несовместимости в Generic types. Здесь нам нужно просто взять и заменить библиотеку. Благо, в GitHub уже есть энтузиасты, которые написали порт — assertk.

@Test fun example(){
    assertThat(1).isEqualTo(1)
}

assert {
    throw Exception("error")
}.throwsError {
    it.hasMessage("wrong")
}
// -> expected [message] to be:<["wrong"]> 
                         but was:<["error"]>

Следует отметить, что assertk обладает более удобным API и полностью совместима с Kotlin.

Вроде бы все наши проблемы мы «подлечили», ну или хотя бы подставили костыли. Естественно, вы можете не натолкнуться на проблемы, приведенные выше, если на старте проекта будете выбирать библиотеки и технологии, совместимые с Kotlin.

Чем же все-таки хАрош Kotlin?

В дополнение к языковым фичам и синтаксическим конструкциям, могу отметить, что язык очень лаконичный и позволяет строить удобные DSL. В подтверждение покажу пример теста, написанного с применением библиотеки Kirk, которая призвана заменить Selenide для Kotlin.

Пример четко демонстрирует, какого формата DSL можно писать. По сути — это BDD, только в коде, со всеми плюшками в виде строгой типизации, автодополнениями и поддержкой рефакторинга.

Еще одним примером является Gradle Kotlin-DSL. Уже сейчас gradle.build файл можно писать более приятным способом, получая автодополнения и статическую компиляцию. Эта фича пока что не достигла стадии релиза, но я больше чем уверен: когда будет 1.0, Groovy DSL можно будет помахать ручкой и полностью перейти на Kotlin.

Что имеем в итоге?

Kotlin — очень приятный язык. Все, что уже реализовано у конкурентов Java, в нем есть. Конвертировать существующий код на Java в Kotlin немного проблематично. Нет еще пока полной совместимости со всеми самыми популярными Java-фреймворками и библиотеками. Лично я получаю удовольствие от работы с языком. В заключение я не буду давать явных советов — писать или не писать, учить Kotlin или хейтить и идти учить JavaScript. Я просто оставлю вам ссылочку на свежий репорт от Rebel Labs о состоянии Java-экосистемы, в котором Kotlin назван самым любимым языком c коэффициентом удовлетворенности 9.1 из 10.

Спасибо, что читали. Всегда думайте головой, не ведитесь на хайп и маркетинг. Выбирайте технологии под свои задачи.

Похожие статьи:
Компания Astell&Kern представила на российском рынке новую модель Hi-Fi плеера AK320, который внешне сочетает флагмана линейки с элементами...
Компания Panasonic Россия представляет новую серию беспроводных DECT телефонов KX-TGJ3XXRU, сочетающих в себе функциональность, стильный...
Богдан Тодчук — Full Stack Developer у Modus X, Dtek Group, який втім має незвичне хобі, що межує з бізнесом. На дозвіллі розробник майструє...
Чтобы ответить на популярные вопросы начинающих программистов о том, стоит ли учить такой-то язык и связывать с ним...
11 серпня Президент України Володимир Зеленський підписав Закон «Про стимулювання розвитку цифрової економіки...
Яндекс.Метрика