Есть много сравнений между Cypress и Selenium, но у каждого есть немного другой взгляд на вещи, поэтому я здесь, чтобы поделиться своим собственным опытом и идеями.

Некоторая предыстория

Как консультант по автоматизации тестирования, я выполнил множество проектов с использованием Selenium, в основном на C # и Java, а также на Python. Я также писал и учил писать модульные тесты на JavaScript, но сделал только один POC (Proof of Concept) с использованием JavaScript и Selenium. Я также делал множество проектов на других языках и инструментах помимо Selenium.

В большинстве проектов автоматизации тестирования, которые я выполняю, я следую довольно строгому методу написания тестов и инфраструктуры (как описано в этом сообщении в блоге и как подробно описано в моей книге Полное руководство по автоматизации тестирования). Мой метод дает несколько преимуществ:

  1. Очень читаемый код (и тесты)
  2. Очень модульный и удобный в обслуживании код
  3. Выявить основную причину сбоев довольно просто.

Я также активно использую объектно-ориентированное программирование и склонен полагаться на строгую типизацию для предотвращения ошибок. Вот пример типичного теста, который я бы написал на C #:

Клиент, для которого я работал над проектом, попросил работать с JavaScript, поскольку его разработчики пишут на JavaScript, и он хочет, чтобы разработчики в какой-то момент взяли на себя ответственность за автоматизацию тестирования. Поскольку мне нравится использовать строгую типизацию, а также потому, что разработчики также были готовы начать использовать TypeScript, мы договорились, что я тоже буду использовать TypeScript вместо чистого JavaScript.

Попытка Selenium

Сначала клиент хотел, чтобы тесты можно было запускать в нескольких браузерах (в основном Chrome и IE…) и платформах, а также использовать для этого Selenium Grid, поэтому Selenium (в отличие от Cypress) был единственным жизнеспособным выбором.

Я начал писать тесты и фреймворк, как я привык к другим языкам, а именно: сначала написать тестовую функцию, вызвав другие функции (которые сначала выдают только «нереализованное» исключение), которые описывают высокоуровневые операции тест в приложении, а затем реализовать каждую из этих функций, чтобы делать то, что она должна. Обратите внимание, что обычно функциональные автоматизированные тесты являются последовательными по своей природе (в рамках одного теста; нагрузочное тестирование - это совсем другая история…). Это означает, что нет смысла начинать какую-либо операцию до завершения предыдущей. Мало того, что в этом нет смысла, это может быстро сделать ваши тесты нестабильными, поскольку порядок, в котором завершается операция, может повлиять на результат так, как вы не можете предвидеть.

Однако в JavaScript (и TypeScript) все операции, которые могут занять более пары миллисекунд, являются асинхронными по своей природе. Это означает, что почти все функции Selenium также являются асинхронными из-за этого, и поэтому используют Promises для обработки этой асинхронной природы. Но даже несмотря на то, что мы используем Selenium только в наших функциях нижнего уровня, эта асинхронная природа должна проникать и в функции более высокого уровня, и в наш тестовый код. Очевидно, что в ES6 мы можем использовать ключевое слово await вместо вложенных then(…) операторов, так что на первый взгляд это лишь небольшое синтаксическое изменение по сравнению с тем, как я пишу тесты на других языках. Вот как тест, аналогичный тесту в приведенном выше примере C #, будет выглядеть в JavaScript (с использованием Jasmine):

Это выглядит немного загроможденным всеми этими await, но это не так уж и ужасно.

Однако с этими await есть еще две тонкие проблемы:

  1. Если вы забудете поставить один, будет довольно сложно понять, что вы пропустили.
  2. Даже если вы этого не сделаете, но тест не прошел внутри какого-то внутреннего метода, полученная вами трассировка стека бесполезна.

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

На тот момент все мои знания о Cypress были получены от чтения и общения с людьми, но у меня не было практического опыта с этим. Я знал, что (по крайней мере, в настоящее время) он работает только в Chrome; работает внутри браузера, поэтому быстрее; Я знал, что вы можете легко отправлять запросы Rest API от него, а также имитировать или шпионить за запросами XHR, которые отправляет страница, и я видел несколько примеров кода, которые выглядят примерно так:

Видеть? Нет awaits! Я предположил, что это было возможно в Cypress, потому что он работает внутри браузера, в отличие от Selenium, который общается с браузером извне.

Мой первый опыт работы с кипарисом и то, что я обнаружил

Поэтому я просмотрел Руководство по началу работы Cypress и некоторые из более конкретных руководств, чтобы понять, как использовать кипарис. Прошло совсем немного времени, пока я не понял, что этот, казалось бы, синхронный код - всего лишь иллюзия и что команды Cypress на самом деле не синхронны, по крайней мере, когда они смешаны с любым обычным, не кипарисовым , Код JavaScript. Уловка, которую использует Cypress, заключается в том, что все его команды на самом деле не выполняются при вызове их соответствующих функций, а скорее эти функции только ставят эти команды в очередь для последовательного выполнения сразу после завершения самой тестовой функции. Это еще не все, но это основная идея. Я намерен вскоре написать еще один пост в блоге, более подробно описывающий, как работает кипарисовик.

Это интересное открытие о Кипарисе действительно застало меня врасплох. Я думал, что это работает одним способом, в то время как на самом деле он работает в совершенно другой парадигме, которая была для меня новой.

Эта парадигма имеет множество тонких последствий и способов, характерных для Cypress, которые необходимы для достижения вещей, которые выполняются с использованием прямого JavaScript с Selenium (или на любых других языках и технологиях автоматизации). Я нашел сам Cypress, а также его документацию (которая, кстати, очень подробная и исчерпывающая) очень самоуверенной. В большинстве случаев эти мнения совпадали с моими собственными, но не всегда, и в этих случаях я чувствовал себя как в ловушке.

Другие ограничения Cypress

Вдобавок я понял, что есть еще несколько ограничений:

  • Из-за политики одинакового происхождения тест привязан к тому же веб-сайту и не может перейти на другой сайт, даже по ссылке с этого веб-сайта.
  • Имеет ограниченную поддержку iframe
  • Вы не можете открыть более одного экземпляра браузера или вкладки в тесте
  • Поскольку браузер представляет собой песочницу, вы не можете выполнять такие действия, как вызов внешних процессов, прямой доступ к БД и т. Д. Cypress позволяет вам делать это, написав плагины задач, которые выполняются на стороне Cypress на NodeJS (Cypress запускает процесс Node, который организует тесты, которые выполняются внутри браузера). Хотя он предоставляет способ сделать это, это более громоздко, чем делать это непосредственно из Node, как если бы вы использовали Selenium.
  • Хотя и Selenium, и Cypress имеют открытый исходный код, Cypress разрабатывается специализированной коммерческой компанией, которая продает дополнительный продукт, что особенно актуально для проведения тестов в CI и параллельно с более чем 3 пользователями. Хотя надо признать, что ценообразование у них очень справедливое.

Преимущества кипариса

Понятно, что у Cypress тоже есть свои преимущества. Вот некоторые примеры:

  • Автоматическая повторная попытка поиска элементов и, в основном, всех действий, которые не меняют состояние (например, щелчок)
  • Автоматическая прокрутка, чтобы убедиться, что элемент находится в поле зрения, прежде чем щелкнуть по нему
  • Может отправлять, шпионить и перехватывать запросы XHR. Это делает его подходящим как для модульных, так и для интеграционных и системных тестов в одном месте.
  • Поддерживает шпионов и заглушек (стиль модульного тестирования)
  • Отличная документация. Как справочник, так и лучшие практики

Основное различие между селеном и кипарисом

Со всеми этими плюсами и минусами, и хотя мы можем сравнивать Selenium и Cypress с разных сторон, есть одно ключевое различие между ними, от которого и проистекает большинство других различий: Cypress - это среда тестирования, а Selenium - это программное обеспечение. компонент. Это означает, что Selenium - это просто довольно низкоуровневый строительный блок (хотя и очень важный и хороший!), И вы должны интегрировать его с другими инструментами, такими как среда тестирования (например, Jasmine), ведение журнала, отчетность и многое другое. другие вещи для создания всего вашего решения. Для многих из этих интеграций вам нужно написать код самостоятельно, а затем поддерживать его. Cypress, с другой стороны, пытается дать вам все необходимое для начала работы и дает вам возможность сосредоточиться на самих тестах.

Одна из самых приятных вещей в Cypress - это интерактивный Test Runner. Средство выполнения тестов не только автоматически регистрирует все действия, но и для каждого действия сохраняет моментальный снимок модели DOM. После завершения теста он позволяет вам перемещаться вперед и назад во времени, чтобы увидеть не только статический снимок экрана страницы во время действия, но и реальную интерактивную страницу, какой она была на тот момент. Затем вы можете открыть инструменты разработчика Chrome и исследовать DOM и внутреннее состояние приложения с помощью консоли DevTool.

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

Решение остаться с Cypress

Взвесив все эти факторы, я решил остаться с Cypress, так как в целом, привыкнув к его способу работы, я заметил, что в целом я более продуктивен с его помощью. Кроме того, поскольку мне скоро придется передать свой код разработчикам моего клиента, я считаю, что им будет проще использовать и поддерживать базу кода, в которой будет гораздо меньше «связующего кода», чем в весь фреймворк, который мне пришлось бы писать практически с нуля, если бы я решил использовать Selenium.

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