Как Kotlin может помочь в тестировании API: кейс Русфинанс Банка

—

от автора

Заявленный в заголовке Kotlin больше ассоциируется с Android-разработкой, но почему бы не поэкспериментировать? Мы с его помощью нашли способ немного упростить автоматизацию тестирования API одного из наших сервисов, а также облегчить работу тестировщикам, мало знакомым с программированием и нюансами языка Java.

Чем мы занимаемся? Разрабатываем сервис для отправки брокерских анкет для расчёта и получения решения по ним. И несмотря на то, что это банковское решение, разработку ведёт небольшая scrum-команда, тестированием в которой занимаются 1-2 специалиста в зависимости от загрузки и ситуации на проекте.

Под катом расскажем о результатах наших экспериментов, которые мы с удовольствием перенесли в продакшн.

Без лица

Наш сервис разрабатывался для интеграции с интерфейсом партнеров и не имеет собственного UI. Поэтому в данном случае тестирование API напрямую — это единственный доступный вариант. Хотя и при наличии интерфейса API-тесты обладают рядом преимуществ:

  • позволяют начать тестирование уже на этапе разработки сервисов,
  • упрощают локализацию ошибок,
  • в целом уменьшают время на тестирование.

Наш сервис включает в себя набор API для передачи данных анкеты клиента на расчёт и для получения решения по автокредиту. В качестве основных высокоуровневых задач по тестированию можно выделить следующие проверки:

  • формат полей и параметров,
  • корректность кодов состояния и сообщений об ошибках,
  • обязательные поля и логика сервисов.

Переломный момент

MVP сервиса команда подготовила в очень сжатые сроки, а автоматизированные тесты изначально были написаны разработчиком продукта. Автотесты было быстрее и удобнее включить в проект, поэтому изначально они были тесно связаны его с кодом и базировались на стеке Java, REST-assured, с тестовым фреймворком TestNG.

С развитием проекта росла вовлеченность тестировщиков в процесс автоматизации. На данный момент задачи поддержки и обновления автотестов лежат полностью на отделе тестирования. В связи с этим появилась необходимость скорректировать подход к автоматизации — максимально упростить тесты и сделать их независимыми от основного кода. И, тем самым, решить возникающие трудности:

  1. Связь с кодом делает тесты более уязвимыми к любым проектным изменениям, требует больших трудозатрат на поддержку работоспособности.
  2. Сложные взаимосвязи увеличивают время на поиск информации и расследование ошибок.
  3. К работе с Java кодом сложно подключать новых сотрудников отдела тестирования, требуется обучение тестировщиков и значительное время для ввода в проект.

Поэтому мы решили изменить подход к тестированию и сформулировали следующие требования к новым инструментам:

  1. Полная совместимость с Java, позволяющая переписывать проверки поэтапно, при этом продолжая работать со старыми тестами.
  2. Простой, интуитивно понятный код.
  3. Бесплатность и стабильность языка.
  4. Выделение автотестов в отдельный проект.

Причём тут Kotlin

Нашим потребностям максимально отвечает язык Kotlin.

Кроме полной совместимости с Java в Kotlin нас заинтересовали следующие особенности:

  1. Лаконичность языка делает код наглядный и легко читаемым.
  2. Синтаксический сахар.
  3. Интуитивно понятный код и легкое вхождение специалистов в проект.
  4. Возможность переводить автотесты с Java на Kotlin постепенно и безболезненно, при необходимости частично.

Минусы, безусловно, тоже имеются, особенно в сравнении с Java. Во-первых, относительно небольшое сообщество: найти помощь и ответы на вопросы по Java гораздо проще, чем в случае с Kotlin. Во-вторых, в целом Java — более универсальный язык с большими возможностями и большим количеством наработок и библиотек.

Но, честно говоря, для целей тестирования нам не нужны настолько широкие возможности, которые может дать лишь Java. Поэтому мы отдали предпочтение простоте и лаконичности Kotlin.

От слов — к делу

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

В Kotlin можно инициализировать объект запроса с помощью одной строки кода. Например, класс ApplicationDTO (для отправки анкеты на решение) и ErrorDTO (ошибки, приходящие от сервиса) выглядят так:

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

Аннотация JsonIgnoreProperties позволяет не указывать все поля в классе, если для тестов они не нужны и их не нужно проверять. Если придёт какое-то поле, не указанное в описании, тест не упадёт с ошибкой.

Вопросительный знак у типа переменной показывает, что в какой-то момент она может принимать значение null. Но при использовании переменной это нужно будет не забыть учесть и обработать. Наконец, в отличие от тестов на Java, здесь можно изящно избежать NullPointerException.

Проиллюстрируем на простом примере проверки ошибки при некорректном логине:

class ApplicationTests {      val DEFAULT_LOGIN = "consLogin"     val ERROR_CODE = "3"     val BASE_URI = "https://base_url.com"      companion object{         private var spec: RequestSpecification? = null          @JvmStatic         @BeforeClass         fun initSpec() {             spec = RequestSpecBuilder()                     .setContentType(ContentType.JSON)                     .setBaseUri(BASE_URI)                     .addFilter(ResponseLoggingFilter())                     .addFilter(RequestLoggingFilter())                     .build()         }     }      @Test     fun incorrectLogin() {         val incorrectLogin = DEFAULT_LOGIN + "INCORRECT";         val res = given()                 .spec(spec)                 .body(ApplicationDTO)                 .`when`()                 .post(endpointApplication(incorrectLogin)                 .then()                 .statusCode(400)                 .extract().`as`(ErrorDTO::class.java)         assertThat(res.error_message).containsIgnoringCase("Указан неверный логин или пароль")         assertThat(res.error_code).isEqualToIgnoringCase(ERROR_CODE)     } } 

Мы создаем спецификацию для запросов в BeforeClass, которую переиспользуем во всех тестах этого класса. Jacson серриализует и десерриализует json объекты, что упрощает дело: с ними не нужно работать как со строками, из-за этого существенно снижается количество ошибок.

С Kotlin мы существенно сокращаем количество кода, а значит, облегчаем жизнь и «писателям», и его «читателям». Класс ApplicationDTO уже содержит конструктор и некоторые другие методы (hashCode(), copy() и др.) — нам не нужно «перегружать» ими код и начинающие разработчики автотестов не отвлекаются на них. Их не нужно актуализировать при каких-то изменениях, что сокращает время внесения правок в тесты.

Также очень удобно, что Kotlin поддерживает именованные аргументы – код читается довольно легко, и нет надобности самим прописывать сеттеры для классов json объектов.

Пробовать новое — бесплатно

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

В будущем мы планируем развивать новый подход и масштабировать его на другие проекты, переводить остальные тесты API и пользовательского интерфейса на Kotlin.

P.S.: Несмотря на то, что Kotlin ассоциируется в первую очередь с Android- разработкой, сфера его использования, как вы поняли, этим вовсе не ограничивается. Сокращение времени на написание кода, его простота и лаконичность помогут снизить трудозатраты при решении многих задач. Если у нас появятся новые кейсы с Kotlin, мы обязательно расскажем о них тут.

ссылка на оригинал статьи https://habr.com/ru/company/rusfinancebank/blog/510268/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *