Как автоматизировать тестирование сайта с динамическими данными и сделать это быстро |
03.03.2017 12:45 |
Материал основан на реальном проектном опыте. Для начала скажем несколько слов о проекте. Существует сайт букмекерской конторы для принятия ставок онлайн. До начала работ по автоматизации каждый ручной сет регрессионных тестов занимал около двух дней, релизы проводились примерно раз в неделю. Главным ожиданием заказчика от автоматизации было максимально возможное покрытие регресса автотестами, а также ускорение этого процесса. Забегая вперед, отмечу, что сейчас релизы проходят каждый день или через день, а ручная часть тестов (то, что оказалось невозможно автоматизировать по тем или иным причинам) занимает примерно столько же времени, что и прогон автотестов с просмотром результатов. Данные для основного функционала – принятие ставок – представляют собой список матчей различных видов спорта, обновляющийся в реальном времени по web-сокету: В указанных данных можно выделить два главных класса эквивалентности событий: матчи, проводимые в данный момент времени (Live), и матчи, которые еще не начались (Prematch). У этих классов отличаются некоторые поля в таблице матчей. При этом они по-разному обрабатываются сервером. Конечно, для каждого события существуют еще и кнопки с коэффициентами на различные исходы матча (например, первая кнопка означает победу первой команды в основном времени матча). По клику на картинку откроется полная версия По клику на кнопку соответствующие маркеты (исходы события) добавляются в купон, в котором можно сделать различные варианты ставок: отдельно по одному (ординар) или по нескольким (экспрессы и системы) вариантам компоновки событий. После принятия ставка попадает в историю ставок. Это и есть функционал сайта. Основная сложность при написании тестов для таких исходных данных заключается в том, что данные эти полностью динамические и меняются в реальном времени. Нельзя найти подходящий матч и использовать его в тестах постоянно, нужен некий механизм поиска при каждом запуске. Второй важный момент – нужных данных может не быть в принципе. К примеру, соревнования по некоторым видам спорта не проводятся в то или иное время года, матчи могут не сопровождаться видеотрансляцией и т. д. Как работать в тестах с динамическими даннымиОсобенность тестирования динамических данных заключается в следующем: подходящие данные нужно найти в самом начале теста и далее работать с ними на всех этапах проверок. Как правило, они представляют собой некий список, оформленный в явном (например, выпадающий список) или неявном виде (например, колонка таблицы), который можно собрать с помощью одного локатора. Далее по тексту статьи будут встречаться фрагменты кода на Java с использованием стандартного Selenium 2.0 без дополнительных надстроек. Самый простой вариант событий – это когда нас устраивают абсолютно любые данные и дополнительная фильтрация не нужна. Мы просто собираем их в список по локатору: public List<WebElement> getListOfLiveEvents() { Так получается список интересующих нас элементов, с которым уже можно работать, просто запрашивая их по порядковому номеру. Но что же делать, если нам нужно учесть сразу несколько элементов, а получить их в полном объеме затруднительно? Если повлиять на тестовые данные невозможно (как в случае с этим проектом), то, к сожалению, тест завершится ошибкой. И останется только выдать информативное сообщение о случившемся. Поэтому все тесты в проекте с данными, которых «может не быть», содержат проверку следующего вида: List<WebElement> liveEventsWithBets = Как провести фильтрациюОрганизовать дополнительную фильтрацию данных при необходимости можно двумя методами:
С локатором все достаточно просто. В качестве примера приведем xpath, в котором учитывается, что нам нужны кнопки коэффициентов с определенными свойствами (победа первой команды) и не нужны заблокированные кнопки: //a[not(contains(@class,’locked’))][not(contains(@class,'hid Если уж мы заговорили про xpath, очень полезной штукой для поиска нужных элементов являются его оси. Ниже приведен уже встречавшийся нам ранее локатор для сбора списка Live-событий: By liveEvents = By.xpath("//img[@data-ng-if=’::event.isLive’]//ancestor::div[contains(@class, ‘l-events-event’)]"); Таким образом мы привязываемся к желтой картинке LIVE (она видна на первом скриншоте в статье, у всех верхних Live событий). И возвращаясь по оси предков, получаем целиком весь div события. Второй метод сложнее, но зато с его помощью можно организовать и более сложную фильтрацию. Мы воспользуемся такой возможностью xpath как относительный поиск элемента. Относительные локаторы обязательно должны начинаться с точки. Тогда поиск будет осуществляться от родительского элемента, для которого мы вызвали findElement: public List<WebElement> getListLiveEventsWithBets() { Суть этого метода в получении только тех Live-событий, у которых есть незаблокированная кнопка для ставки. Мы получаем изначальный список Live-событий уже знакомым нам методом getListOfLiveEvents(), а затем в цикле ищем доступную кнопку внутри этих элементов. Если поиск findElements(eventsButtonsNotLockedNotHidden).size() возвращает больше 0 элементов, мы записываем соответствующий родительский элемент в результирующий список. В противном случае у такого события нет доступных кнопок, и мы просто переходим к следующей итерации цикла поиска. Можно выполнить также несколько фильтраций в одном методе, сделав еще один подобный цикл перед возвратом результирующего списка, но уже с поиском другого элемента. Если же нам нужны родительские элементы БЕЗ какого-то элемента внутри, то достаточно просто заменить в поиске size()!=0 на size()==0. Недостатком этого метода, по сравнению с первым, является большое количество выполнений тяжелой операции findElements, что довольно серьезно снижает производительность. Следовательно, нужно стараться по возможности найти необходимые элементы за один раз. Как сделать быстроЧто же касается упомянутого в заголовке статьи обещания «сделать быстро», то попробую дать несколько советов, следуя которым, можно уже на первых этапах получить пользу от автоматизации:
ВыводНа данный момент тестовый проект насчитывает порядка 360 небольших и не зависящих друг от друга тестов как для обычной web-версии сайта, так и для мобильной. Время на регрессионные тесты значительно сокращено: с 2 рабочих дней до 2-3 часов. Заказчик имеет возможность выпускать релизы приложения каждый день, как и хотел. Для нас же это хороший и интересный опыт, а также возможность поддерживать и расширять тестовый проект. Ведь в таком динамично развивающемся продукте и автотесты должны актуализироваться соответственно. |