This document discusses how to start test automation. It covers critical aspects to consider like infrastructure, language and continuous integration. It also discusses typical mistakes to avoid such as overengineering or not planning for maintenance. The document reviews programming approaches like principles (KISS, YAGNI, SOLID) and patterns (singleton, builder, factory, decorator). Finally, it provides an overview of existing automation tools like wrappers.
Всем привет! Меня зовут Горбачёв Константин. Я работаю в компании iTechArt автоматизатором около года. Суммарный опыт в автоматизации более 3 лет. Этот доклад является своеобразным обзором наиболее частых ошибок при старте автоматизированного тестирования. Здесь собраны итоги как работы на проекте, так и при проведении тренингов.
Данный доклад будет разбит на 4 смысловых секции, а по его завершению будет секция вопросов и ответов. За лучший вопрос у нас приготовлен подарок от компании. Первая секция делает упор на наиболее критичные аспекты при выборе того или иного инструмента или языка программирования. Во второй секции я расскажу про наиболее распространённые ошибки при написании тестового фреймворка. Третья секция содержит минимальный набор паттернов и подходов к программированию, соблюдение которых если и не позволит предотвратить массовое переписывание и рефакторинг фреймворка, то как минимум сделает его менее болезненным. И в четвёртой секции я расскажу про существующие врапперы над Selenium, к которым можно присмотреться.
И так, начнём. Сейчас мы поговорим про инфраструктуру и языки.
Этот мемас говорит сам за себя. Хотя он больше для фана, однако актуальность свою не теряет. Ничего плохого про людей с различных комьюнити сказать не хочу, но не забывайте, что каждый решает свои проблемы и они могут с вашими пересекаться лишь частично.
Начнём с самого важного: на чём мы будем писать код и наши тесты. Некоторые пункты могут пересекаться между собой.
Исторически сложилось так, что автотесты пишутся на том же языке, что и приложение. В пользу этого подхода приводят единую экосистему, возможность поддерживания автотестов разработчиками и, как вариант, помощь разработчиков, если у автоматизатора не совсем хватает скиллов в программировании.
Как вариант, который я даже лично видел, это выбор автоматизатором ЯП, в котором он имеет больший опыт. Один из случаев – это когда проект имеет узкую задачу, сдаётся и живёт своей жизнью, в течении которой правки либо минимальны либо их вообще нет.
Так же важную роль играет и функциональность, которую необходимо проверить. Не на всех языках есть нужные для этого библиотеки, например для селениума того же, тогда зоопарк из языков неизбежен.
Не стоит забывать, что из себя представляет тестируемая система, где она хостится. Как пример – десктопное приложение под одну конкретную ось.
Следующий пункт это инфраструктура, и она заслуживает большего, чем быть просто одним из вариантов.
Здесь представлено лишь малое количество тестраннеров с различных языков программирования. Их выбор тоже зависит от инфарструктуры. Если кто знаком с платформой .net, то должен знать, что там есть Nunit, xunit и mstest. В своё время у нас был продукт и в качестве CI/CD платформы использовался TFS 2015 он как раз и сыграл роль на составление данного слайда. Как оказалось в то время TFS мог корректно распределять по тестагентам только тесты на MSTest, а т.к. мы этого не знали и настройка инфраструктуры заказчиком закончилась только через несколько спринтов, то мы начали писать тесты на Nunit. Как итог пришлось всё спешно рефакторить.
Кроме написания автотестов нам их придётся где-то запускать. Для этого у нас есть куча возможностей. Бывает, что заказчик уже имеет проплаченный аккаунт в облачном сервисе вроде саус лаба или браузер стэка. Возможно вы захотите их напрямую запускать в докере на своих серверах, тогда не стоит забывать о виртуализации, и да, хоть на дворе и 2019 год, но её может не быть или она может быть отключена.
Возможно вы захотите запускать по старинке через селениум грид, тоже ваше право.
В особых случаях вам понадобится микс, часть тестов на своей инфраструктуре, а часть на облачной, когда подготовка своей требует много сил и времени.
В последнее время всё больше компания в том числе и MS движутся в направлении кросс-платформенности, но всё равно пока что ОС играет свою роль.
Ну и не стоит забывать о громадном количестве CI инструментов, как дженкинс, тфс, тимсити. Каждый из них обладает своими возможностями по интеграции с другим инструментарием, различными плагинами и возможностями.
Кроме обычных технических проблем перед нами могут встать и проблемы на уровне приложения и заказчика.
Рассказывали о случае, что доступ к приложению был только через ремоут десктоп, написание и дебаг автотестов был очень проблематичным, поэтому не оставалось ничего лучшего, как использовать Sikuli, инструмент для поиска нужных контроллов по графическому изображению. Т.е. людям приходилось делать скриншоты и использовать их для клика, печатания текста и т.д., что в свою очередь трудно назвать быстрым и надёжным способом автоматизации.
Также возможен кейс, когда с нашим приложением мы можем делать, что угодно, но есть определённая его часть, которую мы никак не контролируем и которая тоже может оказывать своё влияние на системы и автотесты в частности. Актуально это, когда происходит интеграция с другой командой.
Сложная логика приложения в основном оказывает влияние на построение тестового фреймворка. Здесь вопрос больше стоит в области подхода написания кода. Также в таких случаях стоит задуматься о том, как параллелить автотесты.
Не всегда есть доступ и к хранилищу данных и бывает это по различным причинам. В таких случаях следует задуматься о каких-то предустановленных данных. На одном из проектов заказчик сам руками создавал нужные такие данные с определённым префиксом и по запросу откатывал базу в исходное состояние.
Ну и остаются различные сторонние системы. В основном их тестированием никто не занимается, кроме самих разработчиков этих систем. Но они могут оказывать влияние изменяемыми данными. Как, например, было с одной платёжной скандинавской. Работу с ней приходилось протестировать, но в зависимости от страны, некоторые тарифы и меню изменялось.
В этой секции поговорим о наиболее распространённых ошибках при построении тестового фреймворка.
Дальше я частично вдохновлялся трудами Роберта Мартина, который говорил что “система в исходном состоянии практически до конца не доживает, она постепенно переписывается”
И так на основе его книг и своего опыта я выделил основные пункты.
Под оверинженирингом я подразумеваю паттерн ради паттерна и усложнение фреймворка на начальном этапе. Это в основном касается автоматизации на новом проекте. В таком случае в начале пути ещё не известна чёткая бизнес логика и структура. Будут ли у нас какие-нибудь сущности видоизменятся или нет. Под вопросом чёткое флоу по приложению, до конца не понятно каким финальным будет путь для получения того или иного результата. Начальная стадия – не самое лучшее время для приложения усилий на формировании каких-либо сервисов. Автотесты от приложения мало чем отличаются по своей сути и то и то имеет право на рефакторинг и видоизменение. Главное – найти золотую середину над качеством кода и его структурой и простотой, быстротой его написания.
Трудность сопровождения касается как и написания тестов, так и их запуск локально и на CI системах. Если в последнем случае мы раз настроили и забыли, то с локальным запуском не всё так просто. На моей практике были случаи, когда разработчики меняли UI координально и хотели запускать автотесты локально. Как известно, времени у них сильно много и бэклог имеет свойство забиваться тикетами. Им требовалось чёткое понимание как поменять локаторы и как всё быстро собрать и запустить у себя на машине. Также к написанию тестов могут привлекаться люди мало знакомые с автоматизацией. Например мануальные тестировщики или разработчики. И им тоже есть, чем забить голову по проекту. Поэтому в идеале для них всё должно быть структурировано и понятно.
Не стоит также делать всё и сразу прямо сейчас. Если касаться юая, то сейчас реалии таковы, что на рынке представлено большое разнообразие различных фреймворков, cms систем и библиотек для него. Поэтому для начала стоит уделить внимание тестовому покрытию и стабильности тестов. На длительный прогон при наличии правдивой информации о качестве приложения глаза закроют. Но если у вас тесты будут бегать в параллель за 10 минут и покрыты будут сложные кейсы, но при этом будет много флаки тестов, то тут вопросы возникнут.
Не следует и прибегать ко всему модному и современному. Здесь я не призываю к ретроградству, а хочу лишь подчеркнуть, что каждое решение должно быть взвешанно. Это больше касается мира JS. С одной стороны наличие такого количества инструментов это хорошо, с другой – надо отслеживать заведомо рискованные.
В этой секции поговорим непосредственно о коде.
Как я и говорил всё хорошо в меру. Тот же Page object не панацея от всех бед. Был случай когда мы даже и не использовали данные подход, а дёргали напрямую обёртки над элементами. Такой подход оказался проще и удобнее. Т.к. приложение по сути состояло из одних смарт-элементом и было Single Page Application.
Всё, что будет рассказано на ближайших двух слайдах не призыв к действию и использованию, а лишь минимальный и часто используемый материал, необходимый тем, кто пишет код. За кулисами остаётся гораздо больше.
KISS – keep it simple, stupid. Суть этого принципа состоит в том, что простая система стабильнее усложнённой. Вкратце это значит, что всё должно дробиться на мелкие куски для дальнейшего переиспользования или замены, если в будущем всплывут какие-либо технические подробности, которые на момент написания кода неизвестны.
YAGNI – you aren’t gonna need it. Основная идея – реализовывать только то, что надо здесь и сейчас без задела на будущее. Если какой-то функционал может быть добавлен, но это на уровне слухов, то не следует сейчас об этом задумываться, всё может поменяться.
SOLID - Принцип единственной ответственности (The Single Responsibility Principle)Каждый класс выполняет лишь одну задачу.OOCP[6]Принцип открытости/закрытости (The Open Closed Principle)«программные сущности … должны быть открыты для расширения, но закрыты для модификации.»LLSP[7]Принцип подстановки Барбары Лисков (The Liskov Substitution Principle)«объекты в программе должны быть заменяемыми на экземпляры их подтипов без изменения правильности выполнения программы.»Наследующий класс должен дополнять, а не изменять базовый.
IISP[8]Принцип разделения интерфейса (The Interface Segregation Principle)«много интерфейсов, специально предназначенных для клиентов, лучше, чем один интерфейс общего назначения.»[9]DDIP[10]Принцип инверсии зависимостей (The Dependency Inversion Principle)«Зависимость на Абстракциях. Нет зависимости на что-то конкретное.»[9]
Все эти принципы формируют культуру написания кода и построения архитектуры приложения. Знание и следование им позволит сократить время на согласование различных нюансов по структуре кода. Как итог – снизится порог вхождения в тестовый фреймворк.
KISS – keep it simple, stupid. Суть этого принципа состоит в том, что простая система стабильнее усложнённой. Вкратце это значит, что всё должно дробиться на мелкие куски для дальнейшего переиспользования или замены, если в будущем всплывут какие-либо технические подробности, которые на момент написания кода неизвестны.
YAGNI – you aren’t gonna need it. Основная идея – реализовывать только то, что надо здесь и сейчас без задела на будущее. Если какой-то функционал может быть добавлен, но это на уровне слухов, то не следует сейчас об этом задумываться, всё может поменяться.
SOLID - Принцип единственной ответственности (The Single Responsibility Principle)Каждый класс выполняет лишь одну задачу.OOCP[6]Принцип открытости/закрытости (The Open Closed Principle)«программные сущности … должны быть открыты для расширения, но закрыты для модификации.»LLSP[7]Принцип подстановки Барбары Лисков (The Liskov Substitution Principle)«объекты в программе должны быть заменяемыми на экземпляры их подтипов без изменения правильности выполнения программы.»Наследующий класс должен дополнять, а не изменять базовый.
IISP[8]Принцип разделения интерфейса (The Interface Segregation Principle)«много интерфейсов, специально предназначенных для клиентов, лучше, чем один интерфейс общего назначения.»[9]DDIP[10]Принцип инверсии зависимостей (The Dependency Inversion Principle)«Зависимость на Абстракциях. Нет зависимости на что-то конкретное.»[9]
Все эти принципы формируют культуру написания кода и построения архитектуры приложения. Знание и следование им позволит сократить время на согласование различных нюансов по структуре кода. Как итог – снизится порог вхождения в тестовый фреймворк.
Паттерн – это образец решения некой часто встречаемой задачи.
На самом деле их в разы больше, но приведенных за глаза хватит в большинстве тестовых фреймворков.
Singleton гарантирует наличие лишь одного экземпляра класса в данный момент времени. Может использоваться для ресурсоёмких объектов, например, для создания экземпляра вебдрайвера или подключение к базе данных.
Singleton гарантирует наличие лишь одного экземпляра класса в данный момент времени. Может использоваться для ресурсоёмких объектов, например, для создания экземпляра вебдрайвера или подключение к базе данных.
Builder используется для построения больших объектов. Основная его задача – сократить количество конструкторов класса, когда существует большая вариация возможно объектов. В качестве примера можно привести смарт таблицы. Там могут быть запиненные колонки, различные экшен меню, в колонках вместо текста может быть другой элемент и т.д.
Builder используется для построения больших объектов. Основная его задача – сократить количество конструкторов класса, когда существует большая вариация возможно объектов. В качестве примера можно привести смарт таблицы. Там могут быть запиненные колонки, различные экшен меню, в колонках вместо текста может быть другой элемент и т.д.
Фабрики чаще используются для создания экземпляра вебдрайвера с нужной конфигурацией и параметрами.
Фабрики чаще используются для создания экземпляра вебдрайвера с нужной конфигурацией и параметрами.
Decorator позволяет обернуть объект дополнительным функционалом без изменения самого объекта. Один из основных вариантов применения – добавление логирования и подсветку элементов.
Decorator позволяет обернуть объект дополнительным функционалом без изменения самого объекта. Один из основных вариантов применения – добавление логирования и подсветку элементов.
В заключительной части мы поговорим про существующие врапперы над селениумом.
Врапперы это достаточно холиварная тема. Одни их хаят за отсутствие контроля, а вторые боготоврят за решение определённых проблем. Здесь представлены наиболее популярные врапперы и готовые фреймворки. Самые топовые из них это codeceptjs и selenide. Вокруг них построены хорошие комьюнити, довольно активно развиваются. JDI поддерживает джаву и сишарп, как и атата это уже полноценные фреймворки со своими абстракциями над пейджами. Ну и канопи только недавно начал активно развиваться и популяризироваться. Он поддерживает f# и функциональный принцип программирования.
Есть также нселен под сишарп и селен под пайтон. Они работают до сих пор, хотя уже давно и не развиваются.
Ну и при выборе того или иного инструмента не забывайте, что впервую очередь он решает проблемы его создателя. Хотя многие из них стараются быть универсальным, но пока они находятся в опен-сорсе никто не гарантирует, что недостающий вам функционал будет реализован по первому запросу.
На этом у меня всё. Готов ответить на ваши вопросы.