Прийшов час осідлати справжнього Буцефала🏇🏻Приборкай норовливого коня разом з Newxel🏇🏻Умови на сайті
×Закрыть

Никогда не писали автотесты? Попробуйте Cypress

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Прежде всего хочу отметить, что я не профессиональный автотестер, а Java-программист. Но однажды поступила задача сделать smoke тесты для базовой проверки основных функций приложения, которое недавно поломали изменением в API зависимого сервиса без предупреждения.

Статья будет интересна всем, кто интересовался автотестированием с нуля на JS, но боялся спросить.

Начну с того, что по автотестированию я ничего никогда не читал. Основной преконсепшн был, что автотесты это сложно, потому что по отзывам пока этот Selenium настроишь... Плюс надо учить XPath и PageObject, чего делать вообще не хотелось.

Быстрый поиск по интернету дал более молодые и перспективные инструменты: WebDriver.IO, Pupeteer (а сейчас лучше Playwright) и Cypress. Выбрал последний, купился на красивые обещания и несколько комментов из холиваров по лучшим инструментам для автотестов.

Так выглядит окно браузера запущенного теста. Слева выполненные команды теста и статус, справа просмотр приложение во время исполнения теста:

Вот так выглядит код теста (в Cypress — весь код на JS, а селекторы — это обычные CSS селекторы):

В runtime выглядит так:

Пока искал инструмент для автотестов — в голове у меня была картинка, что тесты можно создавать прямо в браузере, чтобы просто «нажал на запись скрипта» — система записала мои действия (CSS селекторы элементов, на которые я нажимал). Потом я смотрю сгенерированный тест, подправляю селекторы если нужно, и сохраняю в Test Suite. Эх...

Сказка оказалась тогда недостижимой и таких инструментов я не нашел (возможно кто-то в комментах подскажет правильный путь). Но в Cypress подкупило то, что тесты выполняются в настоящем браузере, и даже можно параллельно с выполнением теста исследовать DOM любимыми инструментами разработчика Chrome (если например селектор не сработал — можно открыть консоль и сразу при исполнении теста посмотреть почему).

Из других параметров, которые для меня были важны — я критически не хотел тратить много времени ни на написание (опять про запись теста в браузере), ни на поддержку тестов. Для моих целей этого было вполне достаточно. Просто для информации o Cypress: с момента, как я впервые открыл сайт Cypress, до первого теста, который логинится в приложение — прошел 1 час.

Итак, Cypress, первая страница фреймворка говорит нам что это JavaScript End to End Testing Framework (cypress.io). Далее бегло читаем документацию, она действительно полная, и можно найти ответы практически на все вопросы (все остальное я быстро находил на StackOverflow):

Дальше по списку фичей с сайта:

  • Time travel — каждый шаг выполнения теста в консоли — можно нажать и вернуться на конкретное состояние всего приложения в прошлом, которое отображается прямо в браузере. И это не просто записанная картинка, а реальный DOM, можно откатиться и исследовать страницу через Chrome devtools.
  • Real time reloads — как во всей модерн JS теме, поменяли исходники — в тот же момент произошёл перезапуск теста в браузере (hot reload).
  • Automatic waiting — многие инструкции теста асинхронные, как то переход на страницу, и Cypress сам автоматически дожидается окончания загрузки. Кроме конечно момента, когда вызовы сервера делает приложение.
  • Network traffic control — Cypress может захватывать/видеть вызовы сервера и можно задать инструкцию, чтобы подождать ответ от сервера.
  • Screenshots and videos — во время выполнения теста Cypress записывает видео экрана (MP4) браузера, вместе с инструкциями в окне.

Все это добро конечно же можно запускать и без открытого браузера на CI, используется headless Chrome или Electron.

Но были и некоторые проблемы.

По началу я не знал, что можно ждать окончания XHR запросов на сервер, и вставлял вместо них timeouts, и тесты рандомно падали. Поправил.

Потом через раз работал Hot Reload, постоянно приходилось перезапускать весь Cypress, потому что не было уверенности, что мои изменения применились. Оказалось, что в моей IDE (IntelliJ IDEA) есть такие нехорошие галочки, которые еще и включены по умолчанию, из-за которых получается что сохранение файла — это не сохранение, а eventual сохранение.

Следующая проблема была в том, что мое приложение использовало window fetch для запросов на сервер, а Cypress видит только XHR запросы. Dirty hack из StackOverflow помог (я так понял, что метод fetch удаляется из window, чтобы браузер сделал fallback на XHR вместо fetch):

Далее встала проблема эмуляции мобильного браузера, просто в коде теста user agent перезаписать не получилось, но в отдельном специальном файле — все получилось.

Далее решение CORS—проблемы:

Потом file upload, с наскоку не получилось, стандартные решения не сработали, зато помогла библиотека cypress-file-upload:

Единственная проблема которую я не смог решить — это воспроизводимость теста. А именно стабильные и одинаковые начальные данные для запуска теста (fixtures), это более конфигурационная задача, а не Cypress, но все равно пока нерешенная.

В итоге, Cypress выглядит отличным инструментом для внедрения автотестирования в проект, если:

  1. Есть знание JS
  2. Нет необходимости тестировать во всех видах браузеров начиная с IE6 (на данный момент Cypress поддерживает Chrome, Chromium, Edge, Electron, Firefox). Вот обсуждение темы. Но могу сказать, что год назад, когда я начинал работать с Cypress он поддерживал только последнюю версию Chrome и Electron для запусков без UI.
  3. Хотите быстро сделать тесты и забыть о них, пока кто-то не сломает приложение :)

Cypress: берите и пользуйтесь!

LinkedIn

Похожие статьи

Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

В кипарисе столкнулся с первым минусом — отсутствие оператора IF. И сделал вывод, что это показатель, что он (пока?) не для профессионалов.

П.С. дада, я читал в документации, что надо строить тесты так, чтобы он не понадобился, но это лишает удобства и занимает больше времени. А в моей проблеме (был отдельный топик на доу) — еще и невозможно.

У разработчиков Cypress свое мнение о Conditional testing. Но в принципе IF есть.

Год назад, примерно, сталкивался с этой проблемой и читал их «мнение». Но мою проблему это не решило. «Костыль» из интернета тоже не помог.

А разве Javascript-ового if-a не достаточно? Или вы про какую-то специальную реализацию if-a говорите?

Он не работает(-ал). В доках об этом написано.

Скорее он работает немного не так, как ожидалось на первый взгляд. Выше вы привели ссылку на тему, которую вы создавали. Там проблема не с if-ом. Он-то как раз честно сработал. Тут нужно учитывать особенности дизайна Cypress, по которому каждая команда возвращает какой-то Chainable объект. Из-за этого, в частности, не рекомендуется делать что-то типа:

let myObject = cy.get('some_selector');
myObject.click();
В свое время намучался с такой гадостью. А так if-ы вполне используются, особенно если они применены к обычным переменным, а не к результатам работы команд Cypress.

в моем случае хватило

cy.get('body').then(($body) => {
  // synchronously query from body
  // to find which element was created
  if ($body.find('input').length) {
    // input was found, do something else here
    return 'input'
  }
})
docs.cypress.io/...​ng.html#Element-existence
но это лишает удобства и занимает больше времени

xunitpatterns.com/...​nditional Test Logic.html

Госпаде, зачем это всё, 100500 фреймворков — Cypress, Playwright, Puppeteer, Selenide JS, Webdriver IO. Лучше взять джаву и голый селениум и не париться с всей этой дичью. В том же сайпресе, на сколько я помню, нужно платить за то что бы параллельно гнать тесты. В java + testng, что реран тестов что параллельный запуск настроить это 1 строчка.

Платити не потрібно, дешборд — це звичайна репортилка, ліл.
«Лучше» — суб’єктивне поняття. У кожного інструмента є свої хороші та погані сторони.

Cypress отличный инструмент, с большим комьюнити, и хорошей документацией

Отличный инструмент, после основанного на Selenium протрактора как глоток свежего воздуха.

Пока искал инструмент для автотестов — в голове у меня была картинка, что тесты можно создавать прямо в браузере, чтобы просто «нажал на запись скрипта» — система записала мои действия (CSS селекторы элементов, на которые я нажимал). Потом я смотрю сгенерированный тест, подправляю селекторы если нужно, и сохраняю в Test Suite. Эх...

*пустил слюну* было бы вообще шикарно

спасибо за ссылку! на вид сгенерированный код хорошее начало, если бы ещё ожидание сервера были, хотя в принципе гитхаб есть

ожидание сервера всмысле ответа сервера? можно сделать cy.route({ method: «post», url: «/endpoints/logs/*» }).as("logs«); а потом cy.wait(’@logs’) и будет что надо :) не забыть установить флаг в конфиге «experimentalFetchPolyfill»: true,

с вас $3 за консультацию ;)

3$ с каждого кто прочитает?) хороший бизнес план

Serenity, Selenide взагалі норм штуки. Дивний вибір для джавіста. Хіба шо погратись

Единственная проблема которую я не смог решить — это воспроизводимость теста. А именно стабильные и одинаковые начальные данные для запуска теста (fixtures), это более конфигурационная задача, а не Cypress, но все равно пока нерешенная.

В джаві це можна реалізувати за допомогою анотацій тестових фреймворків на методи:
— для JUnit5 це — @ParameterizedTest
— для TestNG це — @DataProvider i @Factory

Ну з чистим Selenium WebDriver дійсно нелегко з нуля розібратись, але не дуже зрозуміло, чому вибрали саме JS-стек, раз ви джавіст, то в цьому випадку чудово підійде Selenide — selenide.org
Він під капотом вже має багато плюшок чистого Селеніума, які не потрібно знати і настроювати, і як і в Cypress, тест логіну за 15хв можна наконфігурити і все буде літати, код теж легкий для новачків, тим більше що для джава дева.

Плюс надо учить XPath и PageObject,

Можна обійтись і без XPath, знаю людей, які його не юзають. Можна юзати звичайні CSS selectors і в 90% випадків їх вистачає з головою.
Щодо РО — взагалі не зрозумів, що там вчити. Можливо розкажете в коментах більше детальніше, що ви мали на увазі.

Щодо

Пока искал инструмент для автотестов — в голове у меня была картинка, что тесты можно создавать прямо в браузере, чтобы просто «нажал на запись скрипта» — система записала мои действия

Дивіться на Selenium IDE, Katalon Studio, Ghost Inspector — це те, що зразу спало на думку. Але кажуть, що це не дуже good practice юзати такі тули, бо часто складні сценарії генерують не зовсім правильний код.

Time travel, Real time reloads, Network traffic control

Це класно, але я б таке юзав досить рідко, імхо.

Automatic waiting,Screenshots and videos

Selenide має це все під капотом також.

file upload,

Навіть в чистому Селеніумі це робиться одним рядком:
driver.findElement(By.cssSelector("#someId")).sendKeys("C:\\path\to\your\file");

No hate в сторону Cypress, але мені здається, що в цій ситуації ви можете заюзати рішення описані вище, і це буде краще для вас.
А взагалі, все залежить від того, для чого ви вирішили почати писати автотести, яка ціль, що хочете ними добитись і тд.

юзаю тайм тревел і нетворк інспектор для дебагу постійно
юзаю релоуд для ТДД постійно

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

краще не буде, буде так само + витратиш час на міграцію

йому сподобався сайпресс — хай його використовує :)

пс а у селеніда є network stubbing?

юзаю тайм тревел і нетворк інспектор для дебагу постійно
юзаю релоуд для ТДД постійно

прікольно, можливо, я б теж часто юзав, але зараз не попробувавши, мені здається, що рідко.
Хоча тайм тревел все ж таки, корисна фіча, її би юзав часто

краще не буде, буде так само + витратиш час на міграцію

мав на увазі, якщо б спочатку стартувати проект, то краще Selenide

пс а у селеніда є network stubbing?

хз

Можна обійтись і без XPath, знаю людей, які його не юзають

Это не от тестировщиков зависит, а от фронтов, как они дом организуют. Я видел документы, где легко одними цссселекторами обойтись, видел документы, где это невозможно.

за 15хв можна наконфігурити і все буде літати

hello world на спрингбуте тоже можно за 5 минут запустить, но без нормального изучения функционала фреймворка, нормальной работы не получится.

Это не от тестировщиков зависит, а от фронтов, как они дом организуют.

ну так, я це мав на увазі також, коли казав, що 90% випадків можна обійтись без XPath, якраз таки через побудову DOM-дерева.

hello world на спрингбуте тоже можно за 5 минут запустить, но без нормального изучения функционала фреймворка, нормальной работы не получится.

погоджуюсь. тоді відповім більш розгорнуто — можна легко розібратись, як почати писати тести і як масштабувати, підтримувати, їх в майбутньому.

💆‍♂️ а з новою retry фічою то взагалі казка

Якщо вам потрібен зелений білд, але для цього доводиться ховати провтики тест дизайну / недостатнє знання інструмента / відсутність розуміння як він працює в браузері / флекі-баги самого додатку / нестабільний тестовий стенд за перезапусками — чого б одразу не писати `expect(true).to.be.true` і не паритись?

валідний коментар, і я скажу, що я теж думаю, це — антипаттерн. Але коли ви тільки починаєте проект і у вас чіткого уявлення немає як воно то буде працювати, то застосовуємо принцип MVP і Парето — і це працює ± нормально.

як перестане бути достатньо і в прод будуть баги просочуватись — будемо думати і якось фіксати тести а потім і самі фічі. А поки що — і так зійде ;)

У всех ассертов вроде бы как built-in retry механизм, еще до 5го Cypress

Після 5го також. Під ретраями мається на увазі перезапуск цілого тесту, а не конкретної команди.

Подписаться на комментарии