- Что такое cypress-grep
- Workflow на GitHub Actions
- Пустые спеки
- Пропуск отфильтрованных тестов
- Ручной workflow
Что такое cypress-grep
Этот плагин полезен при запуске тестов, умеет запускать их “выборочно” — по части имени, или по тегу. Например, есть возможность размечать тесты тегами (как на примере ниже):
it('loads the page', () => ...) it('searches for items', {tags: '@search'}, () => ...)
Запускаем тест (перед тем поставив плагин и добавив в строку grep
переданное из переменных окружения Cypress):
$ npx cypress run --env grep="loads"
Запускаем второй тест, уже с тегом (grepTags):
$ npx cypress run --env grepTags="@search"
Все другие тесты в файле будут “приостановлены” (со статусом “Pending” — подробнее о статусах в Cypress тут), как если бы применялся метод it.skip
.
- loads the page ✓ searches for items(811ms) 1 passing (811ms) 1 pending
При этом надо учесть, что приостановка (или скорее пропуск) тестов таким способом не увеличивает для вас стоимость Cypress — тесты в статусе “Pending” не учитываются при расчете стоимости.
Сейчас разберем, как эффективно применять grep с тестами и экономить время в CI-процессах, и фильтровать тесты.
Полный код примеров — в репозитории; результаты тестов — на дашборде здесь.
Workflow на GitHub Actions
В проекте было несколько наборов и тестов с тегами разных функций. Также был Github Actions Workflow tags.yml который запускал тесты с тегами по каждой функции отдельно. Например, первый job запускает все тесты с тегом @dynamic
:
tag-dynamic: runs-on: ubuntu-20.04 needs: install steps: - name: Checkout ? uses: actions/checkout@v2 # https://github.com/cypress-io/github-action - name: Run tests ? uses: cypress-io/github-action@v2 with: start: npm run dev wait-on: 'http://localhost:1234' env: grepTags=@dynamic record: true group: '1 - @dynamic' tag: tags env: # pass the Dashboard record key as an environment variable CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
Параллельно, второй job запускает все тесты с тестом @visible
env: grepTags=@visible group: '2 - @visible'
Здесь есть job’ы, которые запускают только тесты с тегами @client
и @intercept
. В конце есть job, который выполняет все тесты untagged.
untagged: runs-on: ubuntu-20.04 needs: [tag-intercept, tag-client, tag-visible, tag-dynamic] steps: - name: Checkout ? uses: actions/checkout@v2 # https://github.com/cypress-io/github-action - name: Run tests ? uses: cypress-io/github-action@v2 with: start: npm run dev wait-on: 'http://localhost:1234' env: grepUntagged=true record: true group: '5 - untagged' tag: tags env: # pass the Dashboard record key as an environment variable CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
Job’ы с тегами выполняются параллельно, а без тегов —untagged
выполняются в конце.
Пустые .spec-файлы (далее спеки)
У нас было 19 .spec-файлов в проекте. Когда запускались только тесты с тегами @dynamic
, что случилось со .spec-файлами в которых не было тестов с таким тегом? Они показывали “ошибку” в Cypress Dashboard (на следующем скрине).
Вы можете видеть, что Dashboard срабатывает не так как мы хотим — потому что он засчитывает одни и те же .spec-файлы снова и снова — tag-dynamic
, затем tag-visible
, затем tag-intercept
, и т.д. И в большинстве из этих файлов нет тестов с тегом, который нас интересует — поэтому они отобразятся как ошибки, и просто заберут у нас дефицитное время в CI.
Можно сделать это правильнее. Плагин cypress-grep
имеет опцию “предпросмотра” .spec-файла, и если нет тегов или grep-строчки которую мы сейчас ищем в названии теста, тесты из этого файла не будут выполнены. Активируем эту опцию переменной окружения:
env: grepTags=@dynamic,grepFilterSpecs=true
А чтобы случайно не забыть активировать эту опцию, можем задать ее в файле конфигурации cypress.json:
{ "env": { "grepFilterSpecs": true } }
После этого CI-job tag-dynamic
немедленно становится намного быстрее — потому что он фильтрует все 19 .spec-файлов, и запустит только те, в которых найдется нужный тег.
Да и каждый job становится быстрее:
tag-dynamic 2m 51s => 1m 7s tag-visible 3m 13s => 2m 26s tag-client 1m 39s => 1m 7s tag-intercept 2m 8s => 1m 4s
Отличный экономный подход, больше не надо открывать 18 .spec-файлов из 19, потому что там нет тестов к выполнению.
Примечание: job’ы c меткой untagged
не подвергаются фильтрации, поскольку опция grepUntagged=true
(пока) несовместима с опцией grepFilterSpecs=true
.
Пропуск отфильтрованных тестов
Если у нас есть .spec-файл с несколькими тестами it
, и мы применяем grep, фильтрованные тесты исключаются при помощи it.skip
. Это может создать непонятки в Command Log и в тестовой аналитике. Например, в этом .spec-файле больше фильтрованных тестов чем выполняемых, если применить grep=”works 2”
А можем применить другую опцию, полного обхода фильтрованных тестов. Она “прячет” тесты которые не выполняются:
{ "env": { "grepFilterSpecs": true, "grepOmitFiltered": true } }
В Command Log и аналитике теперь видим только выполняемые тесты:
В нашем примере todo-graphql-example
удалены из рассмотрения все “скипнутые” тесты. Например, перед тем как мы отфильтровали тесты с тегом “@visible”:
TodoMVC with GraphQL cy.intercept - completes the first todo ✓ stubs todos query (518ms) ✓ shows loading indicator (490ms) - adds and deletes todo - stubs by checking operation name ✓ spies on adding todos (499ms) - intercepts operations using custom header 3 passing (2s) 4 pending
После того как добавили опцию grepOmitFiltered=true
, в выводе будут только тесты с тегом:
TodoMVC with GraphQL cy.intercept ✓ stubs todos query (515ms) ✓ shows loading indicator (491ms) ✓ spies on adding todos (493ms) 3 passing (2s)
Это уже намного лучше.
Ручной workflow
Можно добавить новый workflow в проект; который мы будем активировать вручную в любое время когда запускаем отдельный тест или группу тестов. Пример такого workflow в файле grep.yml.
name: grep on: workflow_dispatch: inputs: grep: description: Part of the test title required: false grepTags: description: Test tags required: false burn: description: Number of times to repeat the tests required: false jobs: grep: runs-on: ubuntu-20.04 steps: - name: Checkout ? uses: actions/checkout@v2 # https://github.com/cypress-io/github-action - name: Run filtered tests ? uses: cypress-io/github-action@v2 with: start: npm run dev wait-on: 'http://localhost:1234' env: grep=${{ github.event.inputs.grep }},grepTags=${{ github.event.inputs.grepTags }},burn=${{ github.event.inputs.burn }} record: true group: 'grep=${{ github.event.inputs.grep }},grepTags=${{ github.event.inputs.grepTags }},burn=${{ github.event.inputs.burn }}' tag: grep env: # pass the Dashboard record key as an environment variable CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
Давайте проверим, надежен ли тест в “cors-spec.js”. Запустим его 5 раз подряд. Из GitHub-интерфейса запустим workflow со следующими параметрами:
Параметры grep
, grepTags
и burn
передаются в Cypress через env: …
. Только один .spec-файл имеет название отвечающее строке в grep
. И этот тест был выполнен пять раз подряд.
Cypress Dashboard показывает один .spec-файл с 5 выполненными тестами, в названии видим наши параметры:
На этом все.