Сквозные тесты с Cypress

Glarus BI использует Cypress для «сквозного e2e-тестирования», то есть тестов, которые выполняются для приложения в целом, включая внешний интерфейс, серверную часть и базу данных приложения. Эти тесты, по сути, представляют собой сценарии, написанные на JavaScript, которые запускаются в веб-браузере: посещайте разные URL, щелкайте различные элементы пользовательского интерфейса, вводите текст и подтверждайте, что все происходит так, как ожидалось (например, элемент появляется на экране или выполняется сетевой запрос).

Начало работы

Тесты Cypress в Glarus BI расположены в e2e/test/scenarios в структуре, которая примерно отражает структуру URL Glarus BI. Например, тесты для административных страниц «модели данных» расположены в frontend/test/metabase/scenarios/admin/datamodel.

Во время разработки вы можете запускать yarn build-hot для непрерывной сборки внешнего интерфейса и yarn test-cypress-open для открытия приложения Cypress, где вы можете выполнять тесты, над которыми работаете.

Чтобы запустить все тесты Cypress программно в терминале:

yarn run test-cypress-run

Вы можете запустить определённый набор сценариев, используя флаг --folder, который подберёт выбранные сценарии в e2e/test/scenarios/.

yarn run test-cypress-run --folder sharing

Вы можете быстро протестировать один файл только с помощью флага --spec.

yarn test-cypress-run --spec e2e/test/scenarios/question/new.cy.spec.js

Тестовые файлы Cypress структурированы как тесты Mocha, где блоки описания используются для группировки связанных тестов, а блоки it представляют собой сами тесты.

describe("homepage",() => {
  it('should load the homepage and...', () => {
    cy.visit("/metabase/url");
    // ...
  })
})

Мы настоятельно рекомендуем использовать такие селекторы, как cy.findByText() и cy.findByLabelText() из @testing-library/cypress, так как они поощряют написание тестов, которые не зависят от деталей реализации, таких как имена классов CSS.

Старайтесь избегать случайного повторного тестирования частей приложения. Например, если вы хотите протестировать что-то в конструкторе запросов, перейдите прямо туда, используя helper, такой как openOrdersTable(), вместо того, чтобы начинать с домашней страницы, нажимая «Создать», затем «Запрос» и т.д.

Документация Cypress

Советы и детали

contains, find и get

В Cypress есть набор похожих команд для выбора элементов. Вот несколько советов по их использованию:

  • contains чувствителен к регистру текста в DOM. Если это не соответствует ожидаемому тексту, убедитесь, что CSS не обновил регистр.

  • contains соответствует подстрокам, поэтому, если вы видите «filter by» и «Add a filter», contains («filter») будет соответствовать обоим. Чтобы избежать этих проблем, вы можете либо передать регулярное выражение, закрепляющее начало/конец строки, либо передать селектор в дополнение к строке: .contains(selector, content).

  • find позволит вам искать в пределах вашего предыдущего выбора. get будет искать всю страницу, даже если она связана.

Увеличьте размер области просмотра, чтобы избежать прокрутки

Иногда представления Glarus BI немного велики для стандартного окна просмотра Cypress размером 1000x660. Для этого может потребоваться прокрутка тестов для работы. Чтобы избежать этого, вы можете увеличить размер области просмотра для конкретного теста, вызвав cy.viewport(width, height).

Перезагрузка кода и тестовая перезагрузка

Когда вы редактируете тестовый файл Cypress, тесты обновляются и запускаются снова. Однако, когда вы редактируете файл кода, Cypress не обнаружит это изменение. Если вы используете yarn build-hot, код будет пересобран и обновлен внутри Cypress. Вам придется вручную щёлкнуть повторно после загрузки нового кода.

Проверка, когда «contains helper» открыт

Одной из замечательных особенностей Cypress является то, что вы можете использовать инспектор Chrome после каждого шага теста. Cypress также предоставляет помощника, который может тестировать вызовы contains и get. Этот помощник создаёт новый пользовательский интерфейс, который не позволяет проверке нацеливаться на правильные элементы. Если вы хотите проверить DOM в Chrome, вы должны закрыть этот помощник.

Помещение неправильного HTML-шаблона в Uberjar

yarn build и yarn build-hot перезаписывают шаблон HTML, чтобы ссылаться на правильные файлы Javascript. Если вы запустите yarn build перед сборкой тестов Uberjar для Cypress, вы не увидите изменений в вашем Javascript, даже если вы затем запустите yarn build-hot.

Запуск Cypress на машинах M1

Вы можете столкнуться с проблемами при запуске Cypress на машине M1. Это вызвано @bahmutov/cypress-esbuild-preprocessor, который использует esbuild в качестве зависимости. Ошибка может выглядеть так. Решение состоит в том, чтобы установить NodeJS с помощью одного из менеджеров версионности Node, таких как [nvm](https://github.com/nvm -sh/nvm) или n.

Запуск тестов, зависящих от образов Docker

Подмножество наших тестов зависит от внешних сервисов, доступных через образы Docker. На момент написания этой статьи это три поддерживаемые внешние базы данных QA, веб-почта и сервер LDAP. Утомительно иметь пять контейнеров Docker, работающих локально. Следующий способ предусмотрен для людей, которые не заботятся об этих тестах, но все же нуждаются в локальном запуске спецификаций, содержащих их. Запустите эту команду:

yarn test-cypress-run --env grepTags="-@external" --spec path/to/spec/foo.cy.spec.js

Обратите внимание на знак «минус» перед тегом @external. Для получения более подробной информации обратитесь к официальной документации.

Запуск тестов с использованием Snowplow

Тесты, которые полагаются на Snowplow, ожидают запущенный сервер. Для запуска:

  • запустите локально Snowplow: docker-compose -f ./snowplow/docker-compose.yml up -d

  • передайте переменные окружения в команду запуска тестов: MB_SNOWPLOW_AVAILABLE=true MB_SNOWPLOW_URL=http://localhost:9090 yarn test-cypress-open

Снимки базы данных

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

Как правило, мы используем моментальный снимок по умолчанию, добавляя before(restore) внутри первого блока describe для восстановления перед запуском всего набора тестов. Если вы хотите использовать снимок помимо стандартного, укажите имя в качестве аргумента для restore следующим образом: before(() => restore("blank")). Вы также можете вызвать restore() внутри beforeEach() для сброса перед каждым тестом или внутри определённых тестов.

Снимки создаются с помощью отдельного набора тестов Cypress. Эти тесты начинаются с пустой базы данных и выполняют определённые действия, чтобы привести базу данных в предсказуемое состояние. Например: зарегистрируйтесь как bob@metabase.com, добавьте запрос, включите настройку ABC.

Эти тесты, создающие снимки, имеют расширение .cy.snap.js. Когда эти тесты запускаются, они создают дампы БД в frontend/tests/snapshots/*.sql. Они запускаются до начала тестов и не фиксируются в git.

Запуск в CI

Cypress записывает видео каждого запуска теста, что может быть полезно при отладке. Кроме того, в неудачных тестах сохраняются изображения более высокого качества.

Эти файлы можно найти в разделе «Артефакты» в результатах каждого запуска в GitHub Actions.

Пример артефактов неудачного теста в каталоге «Onboarding»:Раздел "Artifacts" на GitHub

Запуск тестов Cypress для версии Metabase EE

Перед запуском Cypress для версии Metabase EE установите переменную окружения MB_EDITION=ee. У нас есть специальный блок описания под названием describeEE, который будет пропускать или запускать тесты в зависимости от версии.

Enterprise запустится без премиум-токена!

Если вы хотите протестировать премиум-функции (флаги функций), то действительные токены должны быть доступны для всех тестов Cypress. Мы достигаем этого, добавляя к переменным среды префикс CYPRESS_.

Вы должны предоставить два токена, которые соответствуют планам Metabase EE/PRO с самостоятельным размещением (все функции включены) и облачным планом STARTER (функции не включены).

  • CYPRESS_ALL_FEATURES_TOKEN

  • CYPRESS_NO_FEATURES_TOKEN

MB_EDITION=ee CYPRESS_ALL_FEATURES_TOKEN=xxxxxx CYPRESS_NO_FEATURES_TOKEN=xxxxxx yarn test-cypress-open

Если вы перейдёте на страницу /admin/settings/license, поле ввода лицензии должно показывать активный токен. Будьте осторожны, делясь скриншотами!

  • Если тесты в блоке describeEE выделены серым цветом и не выполняются, убедитесь, что вы запустили версию EE.

  • Если тесты запускаются, но корпоративные функции отсутствуют: убедитесь, что для используемого вами токена включены соответствующие флаги функций.

  • Если с токеном всё в порядке, остановите все процессы Java: запустите killall java и перезапустите Cypress.

Теги

Cypress позволяет нам тегировать тесты, чтобы легко находить определённые категории тегов. Например, мы можем пометить все тесты, которые требуют внешней базы данных, как @external, а затем запустить только эти тесты с помощью yarn test-cypress-open --env grepTags="@external". Теги должны начинаться с @, чтобы было легче отличать их от других строк в поиске.

Вот теги, которые мы используем:

  • @external — тесты, которые требуют внешнего контейнера Docker для запуска;

  • @actions — тесты с использованием действий и изменяющие данные в источнике данных.

Как провести стресс-тестирование ненадёжного теста?

Локальное исправление ненадежного теста (flaky test) не означает, что исправление будет работать в среде CI GitHub. Единственный способ убедиться, что исправление работает — провести его стресс-тестирование в CI. Вот для чего создан .github/workflows/e2e-stress-test-flake-fix.yml. Он позволит вам быстро протестировать исправление в вашей ветке, не дожидаясь завершения полной сборки.

Для этого выполните следующие действия:

Подготовка

  • Создайте новую ветку с предложенным вами исправлением и отправьте её на удалённый компьютер.

  • Пропустите открытие PR, либо откройте черновой запрос на включение.

Запуск рабочего процесса стресс-тестирования вручную

  • Перейдите по ссылке https://github.com/metabase/metabase/actions/workflows/e2e-stress-test-flake-fix.yml.

  • Кликните на триггере Запустить рабочий процесс, находящемся рядом с надписью «Этот рабочий процесс имеет триггер события workflow_dispatch».

  1. Выберите свою собственную ветку в первом поле «Использовать рабочий процесс из» (эта часть имеет решающее значение!).

  2. Скопируйте и вставьте относительный путь спецификации, которую вы хотите протестировать (например, e2e/test/scenarios/onboarding/urls.cy.spec.js), не заключая его в кавычки.

  3. Установите желаемое количество запусков теста.

  4. Если требуется, добавьте grep-фильтр согласно документу.

  5. Нажмите зелёную кнопку «Запустить рабочий процесс» и ждите результатов.

Что следует помнить при использовании этого рабочего процесса

  • Он автоматически попытается найти и загрузить ранее созданный Metabase uberjar, сохранённый как артефакт из одного из прошлых коммитов / запусков CI.

  • Он был предназначен для отладки тестов E2E, которые не требуют нового Metabase uberjar.

  • Если исправление требует изменения исходного кода (либо бэкенда, либо фронтенда), вместо этого откройте обычный PR и позвольте CI сначала выполнить все тесты. После этого вы сможете вручную запустить рабочий процесс стресс-теста, как описано выше, и он автоматически загрузит недавно созданный артефакт из этого запуска CI. Пожалуйста, имейте в виду, что CI сначала должен полностью завершить работу. Рабочий процесс использует GitHub REST API, который в противном случае не видит артефакты.