А у нас новый доклад Ruby Russia 2022. В этот раз поговорим о тестах. Автор этого текста, ведущий инженер по автоматизированному тестированию ПО в Альфа-Банке Елена Рыжкова расскажет, как в компании используют популярный Cucumber, и для чего помимо автоматизации он может быть полезен.
Есть много различных инструментов для автоматизированного тестирования. Каждый проект выбирает свой стек инструментов для автоматизации, основываясь на специфике тестируемого приложения, на опыте других команд, на популярности тех или иных фреймворков. При необходимости тестирования UI многие обращают внимание на Cucumber. Кто-то внедряет Cucumber на своем проекте для применения методологии BDD, кто-то применяет этот инструмент для возможности подключения ручных тестировщиков к написанию сценариев автотестов. Здесь мы поговорим о том, для чего и как мы применяем Cucumber на нашем проекте в Альфа-Банке.
Тестирование и Cucumber
В Альфа-Банке много различных проектов, разрабатываются продукты для внутреннего и для внешнего использования. Для приемки продукта применяется как ручное, так и автоматизированное тестирование. Автоматизация тестирования в основном ведется на стеках с Java или Ruby. Также на многих проектах для автоматизации тестирования применяется Cucumber. Не исключение и мой проект, на котором мы применяем Cucumber для написания сценариев UI-тестов.
Применение Cucumber в проекте автотестов выглядит следующим образом. Есть feature-файлы, которые содержат сценарии тестов, написанные на понятном языке с применением Gherkin-нотаций, и файлы с шагами, в которых описывается логика на языке разработки.
Cucumber поддерживает различные языки программирования. В примере приведена реализация шага на Ruby.
Если посмотреть на цели создания этого инструмента и его назначение, то мы увидим, что Cucumber был нацелен на избежание недопониманий между разработчиками и заказчиками.
Cucumber is not a testing tool. It was born out of frustration with ambiguous requirements and misunderstanding between the people who order the software and those who deliver it.
Aslak Hellesøy, author
Том Стюарт говорит о том что это некий хак, позволяющий подумать об опыте применения ПО, не вдаваясь в подробности реализации.
For me, Cucumber works more like a mind hack than a testing tool. It reminds and invites me to think about the experience of using software separately from the details of its implementation.
Tom Stuart, London Ruby User Group
Мэтт Винн считает, что Cucumber лучше работает как инструмент для размышления и общения с командой, нежели как инструмент для автоматизации.
I wish more people knew it works best as a thinking and collaboration tool, not just an automated checking tool.
Matt Wynne, co-author of The Cucumber Book
И, действительно, Cucumber это не только автотесты, но и коммуникации.
Cucumber — это про коммуникации
Мы разрабатываем приложение для сотрудников Альфа-Банка. На проекте больше 10 команд разработки, которые включают в себя ручных и автотестировщиков. Каждые 2 недели у нас формируется общий релиз с новыми фичами. Приложение содержит много различного функционала, который необходимо тестировать. Сейчас в проекте автотестов больше 1000 feature-файлов со сценариями автотестов и больше 2500 шагов.
Стоит подчеркнуть, что в силу специфики реализации нашего проекта, у нас только UI-тесты. Естественно, что помимо написания новых автотестов нужно как-то поддерживать и актуализировать уже существующие и Cucumber нам в этом помогает — позволяет нам не потеряться в коде и хранить в проекте автотестов аналог тестовой модели, которую пишут ручные тестировщики.
Наши feature-файлы содержат сценарии автотестов на русском языке, которые идентичны тест-кейсам из тестовой модели. Также Cucumber разделяет сценарии и описание шагов, что задает определенную структуру проекта автотестов. За счет этого мы можем:
Легко актуализировать существующие автотесты.
Обсуждать сценарии автотеста с командой как обычные тест-кейсы.
Обсуждать реализацию шагов с автоматизаторами, не вдаваясь в подробности сценария.
Легко погружать тестировщиков в автоматизацию, как новых автоматизаторов, так и ручных тестировщиков.
Легко передавать автотесты на сопровождение другому автоматизатору при передаче функционала одной команды в другую.
Получать понятные отчеты о прогоне автотеста.
Копировать шаги из сценария автотеста для составления bug report.
Русский язык в сценариях
Все перечисленные выше возможности также достигаются за счет применения русского языка во время написания сценариев в feature-файлах.
В примере видим простой и понятный сценарий теста. У нас полностью русскоязычная команда и нет необходимости писать сценарии на английском, что многое упрощает. Например, не приходится дополнительно продумывать как правильно сформулировать фразу на другом языке или как перевести то или иное слово. Не у всех идеальное знание языка, и, скорее всего, возникли бы трудности с пониманием.
Не считая описанных возможностей Cucumber, которыми мы активно пользуемся на проекте, ещё есть интеграция со средой разработки и запуск автотестов.
Интеграция с VSCode
Cucumber может интегрироваться с различными средами разработки, например, с VSCode. Мы можем установить плагин для Cucumber и получить возможность:
Использовать автодополнение при написании сценариев.
Проваливаться из сценария к определенному шагу и к его реализации.
Использовать много других полезных функций.
Запуск автотестов
Мы используем тэги Cucumber для запуска автотестов.
У нас есть обязательные теги для каждого сценария, по которым настраиваем запуски в Jenkins или запускаем тесты вручную:
Тег с наименованием команды, которая ответственна за описанный в тесте функционал.
Тег с номером теста. Номер теста берется из тестовой модели ручных тестировщиков. Этот идентификатор указывает на принадлежность сценария к тому или иному функционалу и его порядковый номер в тестовой модели.
Такое тегирование позволяет запускать каждый тест по отдельности, что очень полезно при отладке или для перезапуска теста после его падения в общем прогоне. Также можно запустить все сценарии команды, например, при стабилизации новых поставок.
Применение Cucumber с русским языком наложило определенные ограничения на разработку автотестов, которые за годы существования проекта автоматизации вылились в серьезные проблемы:
дублирование шагов из-за отсутствия единого шаблона для именования,
дублирование кода, сложность в сопровождении, увеличение трудозатрат на автоматизацию из-за неудачного подхода для работы с русскоязычными наименованиями элементов страницы.
Если проблему с именованием удалось решить за счет введения общих правил на проекте, то с решением второй проблемы все оказалось не так просто.
Для наших автотестов мы используем Cucumber, SitePrism, Capybara, Selenium. Сценарии пишем в feature-файлах, описываем Cucumber-steps, из которых вызываем методы объекта страницы. Для взаимодействия со страницами приложения применяем паттерн Page Object, описывая каждую страницу в виде класса с перечнем элементов и методами для взаимодействия с ними. Все стандартно, как у многих в проектах автоматизации. Но... Библиотека SitePrism, которая позволяет реализовать паттерн Page Object, предполагает, что элементы страницы (кнопки, поля и пр.) будут именоваться на английском языке и для взаимодействия с ними необходимо обращение по этому наименованию. К сожалению, на момент внедрения этой реализации в проект автотестов пришли к неудачному решению с тем, как мапить наименование элемента на русском из сценария в feature-файле с наименованием элемента в классе страницы. Было принято решение использовать оператор case (пример реализации приведен ниже).
Такая реализация привела к разрастанию кода для описания класса страницы, к дублированию кода и невозможности применения наследования для универсальных методов. Также это приводило и к дублированию cucumber-steps. Все эти факторы увеличили трудозатраты на написание автотестов в разы. Для решения этой проблемы мы доработали библиотеку SitePrism таким образом, чтобы элементы страницы в классе можно было именовать на русском языке и работать с ними по этому наименованию. За счет этой доработки мы:
избавились от case для маппинга, в котором больше нет необходимости;
вынесли универсальные методы для работы с элементами в родительский класс, составив библиотеку cucumber-steps с общими шагами;
удалили файлы с cucumber-steps для страниц, которым достаточно общих шагов;
удалили из описания классов страниц все общие методы, оставив только уникальные.
В итоге класс страницы, для которой достаточно шагов из общей библиотеки превратился в пример ниже.
Таким образом, доработка позволила исправить очень давнюю проблему и снизить трудозатраты на описание новых страниц приложения. В настоящее время работа по описанию новых страниц выглядит следующим образом: мы просто создаем класс для страницы и описываем элементы. Если нет необходимости в каких-то уникальных для взаимодействия со страницей шагах, мы используем шаги из общей библиотеки, и уже можем работать со страницей из автотеста. Количество шагов (более 2500 степов на проекте), указанное ранее, это результат применения case для маппинга наименований элементов. Сейчас мы находимся в процессе рефакторинга, выполняя указанные выше действия по исправлению проблемы, поэтому в дальнейшем это число должно сократиться в разы.