Оптимизируем автоматизацию: как мы ускорили автотесты в 3-4 раза, сохранив старые наработки

    Автотесты на проектах нужны. Но, как говорится, автоматизация на вкус и цвет может быть разная. Мы пришли на проект, где уже были автотесты, и смогли улучшить покрытие и ускорить прохождение тестов без фундаментальной революции. Под катом о том, как нам это удалось.

    image

    Пара слов о проекте


    Хотя детали проекта мы не можем раскрыть из-за NDA, в общих чертах задача выглядела следующим образом. Мы подключились к разработке fintech API-сервиса, который взаимодействовал с базой данных, возвращая необходимые финансовые объекты (цены, тарифы и прочее). Нашей задачей было тестирование мобильных клиентов для этого сервиса — как web, так и нативных мобильных приложений.

    Автоматизация тестирования на этом проекте развивалась постепенно, вместе с усложнением сервиса. Вероятно, так в свое время появились длинные end-to-end-тесты, которые мы и застали на проекте. Большая часть из них к тому моменту уже не работала, поскольку сервис изменился, а тесты поддерживать было некому — единственный автоматизатор покинул проект задолго до нашего появления.

    Даже те тесты, которые вроде бы соответствовали функционалу, порой падали из-за путанницы с версиями или недоступности внешних ресурсов. Для тестирования использовалась отдельная инфраструктура — тестовые стенды, где для экспериментов разворачивались необходимые версии. Доступ к ней имели разные рабочие группы, и они не всегда действовали согласованно. В результате действий одной группы мог отвалиться какой-нибудь важный API, используемый нашим сервисом, из-за которого даже работающий тест переставал проходить. Т.е. тест уже не показывал работоспособность самого сервиса, а относился скорее к тестовой инфраструктуре в целом.

    Как мы подошли к хаосу


    Казалось бы, в этой ситуации надо бросать все старые наработки и строить тестирование заново. Но мы поступили более “гуманно”. Саму структуру тестирования сохранили, сосредоточившись на решении конкретных проблем — медленном проходе тестов, их нестабильности и недостаточном покрытии тест-кейсами. Для каждой из них нашлось свое решение.

    Рефакторинг


    В первую очередь мы частично переработали код старых тестов, опираясь на более современные паттерны проектирования.

    Часть легаси-кода пришлось убрать — его было слишком сложно поддерживать. В другой части мы выловили все слабые места — заменили по дефолту sleep нормальным wait-ерами, вынесли подготовку ко всем тестам в глобальные setup через аннотации тест-раннеров и т.п. Множество мелких шагов позволило сократить проход среднего end-to-end теста с 3-4 до 1-2 минут.

    Атомарный подход


    Чтобы ускорить создание новых тестов и упростить поддержку старых, мы ушли от громоздких end-to-end-кейсов.

    Лично я ничего принципиального против end-to-end-тестирования не имею, однако в том случае, когда нужно проверить один конкретный экран (а то и часть информации на нем), проходить все этапы, начиная с авторизации пользователя, слишком накладно. Представьте, что мы тестируем интернет-магазин и нам требуется проверить только чек, который отправится покупателю после приобретения определенного товара. Вместо того, чтобы выудить из системы только один экран, мы бы заходили по логину и паролю, выбирали товар, подтверждали покупку и т.п. — выполняли бы множество шагов, не связанных с конкретной задачей тестирования. А ведь на каждый шаг требуется время. Даже со всей проведенной оптимизацией запуск end-to-end-теста занимал до 2 минут, в то время как проверка конкретного экрана — всего 10 секунд. Поэтому там, где это было возможно, мы перешли к таким “атомарным” проверкам, обращающимся только к тому экрану, который нас интересует в рамках тест-кейса.

    Попутно как раз для сравнения экранов мы внедрили snapshot-тестирование, которое позволяет проверять львиную долю UI. Имея тесты и код приложения в одном репозитории, мы можем в тестах задействовать методы этого приложения, т.е. поднимать любые экраны, которые нужны в этом процессе. Так мы можем находить ошибки на сравнении тестовых снимков экранов с эталонными.

    Сейчас snapshot-тестов у нас уже около 300, и их число постепенно растет, поскольку данный подход позволяет существенно сократить время проверки готовой версии перед отправкой ее на продакшн. Весь этот набор тестов запускается автоматически при открытии pull request и прогоняется за 40 минут — так разработчики быстро получают фидбек о проблемах в текущей ветке.

    Безусловно, некоторое количество end-to-end-тестов сохранилось. Без них не обойтись там, где требуется проверка больших бизнес-сценариев, но их имеет смысл запускать, когда все детали уже проверены.

    Мокирование


    Чтобы исключить влияние нестабильного тестового стенда на результат запуска наших тестов, мы запустили мок-сервер. О том, какие решения мы тогда рассматривали и почему выбрали Okhttpmockwebserver, я уже писал на Хабре.

    В результате доля эпизодически падающих из-за внешних причин тестов существенно сократилась.

    Kotlin DSL


    Параллельно мы сделали тесты более читаемыми.

    Те, кто занимаются UI-тестированием, знают, как сложно выискивать истину среди кучи локаторов в длинной “портянке” теста (особенно на той стадии, когда это еще были end-to-end-тесты). В них просто ориентироваться, когда ты на проекте уже два года и даже посреди ночи способен вспомнить, что есть что. Но если ты только пришел, въехать в происходящее — отдельная большая задача. Чтобы новым людям не пришлось каждый раз с ней сталкиваться, мы приняли решение перейти на Kotlin DSL. Он реализуется достаточно просто и имеет простую и понятную структуру. Если раньше тесты состояли из набора одинаковых низкоуровневых вызовов — кликов, ввода текста, скроллов, то теперь все это превратилось в нечто более “бизнесовое” — что-то вроде BDD-подхода. Все видно и понятно.

    На мой взгляд, этим мы сделали определенный задел на будущее. Данный проект однажды уже столкнулся с уходом единственного автоматизатора. Для тестов это закончилось не лучшим образом — их просто перестали поддерживать, поскольку порог входа получился слишком высоким. Для понимания такого сухого кода требовалось много времени и определенная квалификация. Мы же переделали тесты таким образом, что на автоматизацию можно будет в любой момент оперативно перебросить людей с других проектов или из ручного тестирования. Простейшие тесты на Kotlin DSL может писать практически любой. Так автоматизаторам можно оставить низкоуровневую реализацию, а на быстрое написание новых простых тестов подключить людей из команды функциональщиков. У них достаточно познаний в бизнес-логике, и проект только выиграет от того, что они будут больше вовлечены в процесс написания автотестов. Kotlin DSL позволяет описывать тест-кейсы именно так, как они хотели бы видеть все проверки, оставляя низкоуровневую реализацию методов за рамками их работы.

    В целом это все позволило быстрее увеличивать покрытие автотестами. Если раньше на реализацию нового набора тестов (test suite) уходило 16-20 часов, то с новым подходом, в зависимости от сложности тестов, требуется от 4 до 12 часов (а трудозатраты на поддержку сократились с 16-24 до 8-12 часов в неделю).

    Автор статьи: Руслан Абдулин.

    P.S. Мы публикуем наши статьи на нескольких площадках Рунета. Подписывайтесь на наши страницы в VK, FB, Instagram или Telegram-канал, чтобы узнавать обо всех наших публикациях и других новостях компании Maxilect.

    P.P.S. Помогите нам сделать статьи в блоге более интересными: docs.google.com/forms/d/e/1FAIpQLSeqnPceNuK-JopYVxgF15gNWLIi5oM_AZesioCDGXhvr7Y7tw/viewform.
    Maxilect
    94.34
    Умные решения для вашего бизнеса
    Share post

    Comments 2

      +2

      end to end обязательно должен быть. Даже если он медленный и всех страшно бесит. Почему?


      Потому что есть такая скороговорка...


      Ехал mock(а) через mock(у),
      видит mock(a) в mock(e) mock
      Сунул mock(a) mock(у) в mock(у)
      mock за mock(у) mock(у) mock.

      Assertion failed, mock!=mock.


      Т.е. как только у вас не end-to-end, то вы проверяете куски алгоритмов, а не "работает или нет".

        0
        End-to-end сохранились, но только там, где это действительно нужно.

      Only users with full accounts can post comments. Log in, please.