Coder Social home page Coder Social logo

cypress-split's Introduction

cypress-split ci CircleCI cypress version

Split Cypress specs across parallel CI machines for speed without using any external services

Detailed plugin output on GitHub Actions

Blog posts

Videos

Install

Add this plugin as a dev dependency and include in your Cypress config file.

# install using NPM
$ npm i -D cypress-split
# install using Yarn
$ yarn add -D cypress-split

Call this plugin from your Cypress config object setupNodeEvents method:

// cypress.config.js
const { defineConfig } = require('cypress')
// https://github.com/bahmutov/cypress-split
const cypressSplit = require('cypress-split')

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      cypressSplit(on, config)
      // IMPORTANT: return the config object
      return config
    },
  },
})

⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ Important: return the config object from the setupNodeEvents function. Otherwise, Cypress will run all specs. ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️

Cypress versions before v10

// cypress/plugins/index.js
// https://github.com/bahmutov/cypress-split
const cypressSplit = require('cypress-split')

module.exports = (on, config) => {
  cypressSplit(on, config)
  // IMPORTANT: return the config object
  return config
}

Now update your CI script:

GitLab CI

Run several containers and start Cypress using --env split=true parameter

stages:
  - build
  - test

install:
  image: cypress/base:16.14.2-slim
  stage: build
  script:
    - npm ci

test:
  image: cypress/base:16.14.2-slim
  stage: test
  parallel: 3
  script:
    - npx cypress run --env split=true

All specs will be split into 3 groups automatically. For caching details, see the full example in gitlab.com/bahmutov/cypress-split-gitlab-example.

CircleCI

parallelism: 3
command: npx cypress run --env split=true

See the full example in bahmutov/cypress-split-example

Buildkit

npx cypress run --env split=true

The script uses BUILDKITE_PARALLEL_JOB_COUNT and BUILDKITE_PARALLEL_JOB environment variables.

GitHub Actions

# run 3 copies of the current job in parallel
strategy:
  fail-fast: false
  matrix:
    containers: [1, 2, 3]
steps:
  - name: Run split Cypress tests 🧪
    uses: cypress-io/github-action@v6
    # pass the machine index and the total number
    env:
      SPLIT: ${{ strategy.job-total }}
      SPLIT_INDEX: ${{ strategy.job-index }}

Cypress split on GitHub Actions

Note that we need to pass the SPLIT and SPLIT_INDEX numbers from the strategy context to the plugin to grab. See the full example in bahmutov/cypress-split-example

Jenkins

Sample Jenkins File to run scripts on parallel:

pipeline {
  agent {
    // this image provides everything needed to run Cypress
    docker {
      image 'cypress/base'
    }
  }

  stages {
    // first stage installs node dependencies and Cypress binary
    stage('build') {
      steps {
        // there a few default environment variables on Jenkins
        // on local Jenkins machine (assuming port 8080) see
        // http://localhost:8080/pipeline-syntax/globals#env
        echo "Running build ${env.BUILD_ID} on ${env.JENKINS_URL}"
        sh 'npm ci'
        sh 'npm run cy:verify'
      }
    }

    stage('start local server') {
      steps {
        // start local server in the background
        // we will shut it down in "post" command block
        sh 'nohup npm run start &'
      }
    }

    // this stage runs end-to-end tests, and each agent uses the workspace
    // from the previous stage
    stage('cypress parallel tests') {
      environment {
        // Because parallel steps share the workspace they might race to delete
        // screenshots and videos folders. Tell Cypress not to delete these folders
        CYPRESS_trashAssetsBeforeRuns = 'false'
      }

      // https://jenkins.io/doc/book/pipeline/syntax/#parallel
      parallel {
        // start several test jobs in parallel, and they all
        // will use Cypress Split to load balance any found spec files
        stage('set A') {
          steps {
            echo "Running build ${env.BUILD_ID}"
            sh "npx cypress run --env split=2,splitIndex=0"
          }
        }

        // second thread runs the same command
        stage('set B') {
          steps {
            echo "Running build ${env.BUILD_ID}"
            sh "npx cypress run --env split=2,splitIndex=1"
          }
        }
      }
    }
  }

  post {
    // shutdown the server running in the background
    always {
      echo 'Stopping local server'
      sh 'pkill -f http-server'
    }
  }
}

Other CIs

If you are running N containers in parallel, pass the zero-based index and the total number to the plugin using the environment variables SPLIT_INDEX and SPLIT or via Cypress env option:

# using process OS environment variables
job1: SPLIT=3 SPLIT_INDEX=0 npx cypress run
job2: SPLIT=3 SPLIT_INDEX=1 npx cypress run
job3: SPLIT=3 SPLIT_INDEX=2 npx cypress run

# using Cypress env option
job1: npx cypress run --env split=3,splitIndex=0
job2: npx cypress run --env split=3,splitIndex=1
job3: npx cypress run --env split=3,splitIndex=2

Index starts at 1

Some CIs provide an agent index that already starts at 1. You can pass it via SPLIT_INDEX1 instead of SPLIT_INDEX

job1: SPLIT=3 SPLIT_INDEX1=1 npx cypress run

Split specs based on timings

If you know the spec timings, you can create a JSON file and pass the timings to this plugin. The list of specs will be split into N machines to make the total durations for each machine approximately equal. You can see an example timings.json file:

{
  "durations": [
    {
      "spec": "cypress/e2e/chunks.cy.js",
      "duration": 300
    },
    {
      "spec": "cypress/e2e/spec-a.cy.js",
      "duration": 10050
    },
    ...
  ]
}

You can pass the JSON filename via SPLIT_FILE environment variable or Cypressenv variable.

# split all specs across 3 machines using known spec timings
# loaded from "timings.json" file
$ SPLIT_FILE=timings.json SPLIT=3 npx cypress run

# the equivalent syntax using Cypress --env argument
$ npx cypress run --env split=3,splitFile=timings.json

For specs not in the timings file, it will use average duration of the known specs. The timings file might not exist, in this case the specs are split by name. At the end of the run, the duration of all run specs is printed and can be saved into the timings JSON file. Note: you would need to combine the timings from different runners into a single JSON file yourself.

If the timings file does not exist yet, the timings will be written into the file after the run finishes. If the file exists, and the new timings have new entries or the existing entries are off by more than 10% duration, the merged file is written back. Timing for specs without any passes tests or with failed tests is ignored. You can control the threshold to avoid changing the timings file if the times are too close. For example, to only update the timings file if any duration is different by 20% you can use the environment variable SPLIT_TIME_THRESHOLD

$ SPLIT_TIME_THRESHOLD=0.2 SPLIT_FILE=... npx cypress run ...

See example bahmutov/cypress-split-timings-example.

Note 2: during Cypress execution, the working directory is set to the folder with the Cypress config file. This module tries its best to find the split file by searching the parent folders to the Git repo or root folder.

Adjust the specs

Typically you want to find all specs and split them into chunks. But you can adjust the final list of specs using your own callback function.

// the specs is the list of specs
// determined by the split algorithm
function adjustTheSpecs(specs) {
  // for example, reverse the order of specs
  specs.reveres()
  return specs
}

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      cypressSplit(on, config, adjustTheSpecs)
      // IMPORTANT: return the config object
      return config
    },
  },
})

Using your own callback function you can insert new specs to run at the beginning or run the specs in certain custom order, etc. Make sure the returned value is an array of absolute spec paths.

Preview

You can see how this plugin is going to split the specs using the cypress-split-preview alias

# show the split across N machines
$ npx cypress-split-preview --split <N>
# show the split across N machines based on spec timings
$ npx cypress-split-preview --split <N> --split-file <JSON filename>

Merging timings files

This module includes a bin utility to merge multiple timings files into one. Example:

npx cypress-split-merge \
  --parent-folder partials/ \
  --split-file timings.json \
  --output out-timings.json \
  --set-gha-output merged-timing

The above command finds all timings.json file in the sub folders of partials/ folder and merges them. It saved the result to out-timings.json file and if running on GitHub Actions sets the job output named merged-timing to a stringified single line JSON line.

Write Timings to a Separate File

You can also indicate where the plugin should output the timings, by setting the SPLIT_OUTPUT_FILE environment variable or the corresponding Cypress env variable. This will specify the file where the timings will be written. If SPLIT_OUTPUT_FILE is not set, the plugin will default to using the same file specified in SPLIT_FILE.

# Set the SPLIT_OUTPUT_FILE environment variable
$ SPLIT_FILE=timings.json SPLIT_OUTPUT_FILE=output.json npx cypress run

# Or use the Cypress --env option
$ npx cypress run --env splitFile=timings.json,splitOutputFile=output.json

CI summary

To skip GitHub Actions summary, set an environment variable SPLIT_SUMMARY=false. By default, this plugin generates the summary.

Split component specs

Works the same way as splitting E2E specs. Add this plugin to the setupNodeEvents callback in the component object in the config. See cypress.config.js for example:

// cypress.config.js
const { defineConfig } = require('cypress')
const cypressSplit = require('cypress-split')

module.exports = defineConfig({
  e2e: {
    // baseUrl, etc
  },

  component: {
    devServer: {
      framework: 'react',
      bundler: 'vite',
    },
    specPattern: 'components/*.cy.js',
    setupNodeEvents(on, config) {
      cypressSplit(on, config)
      // IMPORTANT: return the config object
      return config
    },
  },
})

Described in the blog post Split React Native Web Component Tests For Free.

How does it work

This plugin finds the Cypress specs using find-cypress-specs and then splits the list into chunks using the machine index and the total number of machines. On some CIs (GitLab, Circle), the machine index and the total number of machines are available in the environment variables. On other CIs, you have to be explicit and pass these numbers yourself.

// it works something like this:
setupNodeEvents(on, config) {
  const allSpecs = findCypressSpecs()
  // allSpecs is a list of specs
  const chunk = getChunk(allSpecs, k, n)
  // chunk is a subset of specs for this machine "k" of "n"
  // set the list as the spec pattern
  // for Cypress to run
  config.specPattern = chunk
  return config
}

List of specs

Suppose you want to run some specs first, for example just the changed specs. You would compute the list of specs and then call Cypress run command with the --spec parameter

$ npx cypress run --spec "spec1,spec2,spec3"

You can still split the specs across several machines using cypress-split, just move the --spec list (or duplicate it) to a process or Cypress env variable spec:

# using process environment variables split all specs across 2 machines
$ SPEC="spec1,spec2,spec3" SPLIT=2 SPLIT_INDEX=0 npx cypress run --spec "spec1,spec2,spec3"
$ SPEC="spec1,spec2,spec3" SPLIT=2 SPLIT_INDEX=1 npx cypress run --spec "spec1,spec2,spec3"

# using Cypress "env" option
$ npx cypress run --env split=2,splitIndex=0,spec="spec1,spec2,spec3"
$ npx cypress run --env split=2,splitIndex=1,spec="spec1,spec2,spec3"

# for CIs with automatically index detection
$ npx cypress run --env split=true,spec="spec1,spec2,spec3"

Inside the SPEC=.... value you can use wildcards, for example to run all specs inside a subfolder

$ SPEC="cypress/e2e/featureA/*.cy.js" npx cypress run --spec "cypress/e2e/featureA/*.cy.js"

Important: if you are passing the list of specs using --env spec="..." and get the error Cannot parse as valid JSON, switch to using SPEC environment variable, see #79.

# instead of
$ npx cypress run --env spec="..." --spec "..."
Cannot parse as valid JSON

# use
$ SPEC=... npx cypress run --spec "..."

Skip specs

You can pass a list of specs to exclude before splitting up across the machines.

SKIP_SPEC="spec1,spec2" SPLIT=2 ...
# finds the list of specs and removes "spec1" and "spec2"
# before dividing across two machines

Wildcards

If your spec pattern includes wildcards * then they will be resolved using globby module.

# split all specs inside the `cypress/e2e` folder
SPEC="cypress/e2e/**/*.cy.js" npx cypress run --spec "cypress/e2e/**/*.cy.js"
# or the equivalent using --env parameter
npx cypress run --spec "cypress/e2e/**/*.cy.js" --env spec="cypress/e2e/**/*.cy.js"

Random shuffle

You can shuffle the found specs before splitting using a stable seed

$ SPLIT_RANDOM_SEED=42 npx cypress run ...

This is useful to randomize the order of specs to find any dependencies between the tests.

Note: all parallel machines usually compute the list of specs, thus the seed must be the same to guarantee the same list is generated and split correctly, otherwise some specs would be "lost".

Relative specs output

If cypress-split has SPLIT and the index and finds the specs, it sets the list of specs in the config object

setupNodeEvents(on, config) {
  cypressSplit(on, config)
  // config.specPattern is a string[]
  // of absolute filenames
  return config
}

Some situations require relative spec names, for example in Angular component specs. You can transform the specs into relative form yourself before returning the config:

setupNodeEvents(on, config) {
  cypressSplit(on, config)
  if (Array.isArray(config.specPattern)) {
    // change the absolute filenames to relative
    config.specPattern = config.specPattern.map((file) => {
      return file.replace(process.cwd(), '.')
    })
  }
  return config
}

Cucumber feature specs

Should work just the same, see the tested example in bahmutov/cypress-split-cucumber-example

// cypress.config.js
const { defineConfig } = require('cypress')
// https://github.com/bahmutov/cypress-split
const cypressSplit = require('cypress-split')
const cucumber = require('cypress-cucumber-preprocessor').default

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      cypressSplit(on, config)

      on('file:preprocessor', cucumber())
      // IMPORTANT: return the config object
      return config
    },
    specPattern: 'cypress/e2e/**/*.feature',
  },
})

Debugging

To see diagnostic log messages from this plugin, set the environment variable DEBUG=cypress-split. It will give you all information necessary to understand what specs the plugin finds and how it splits them up. Here is an example debug output:

Debug output

Tip: cypress-split uses find-cypress-specs to discover specs. If something is wrong, it is useful to see debug messages from both modules:

DEBUG=cypress-split,find-cypress-specs npx cypress run

for example, if using GitHub Actions:

- name: Run split Cypress tests 🧪
  uses: cypress-io/github-action@v6
  # pass the machine index and the total number
  env:
    SPLIT: ${{ strategy.job-total }}
    SPLIT_INDEX: ${{ strategy.job-index }}
    DEBUG: 'cypress-split,find-cypress-specs'

If you notice that the plugin is not working as expected, and you are registering multiple Cypress plugins, you might be experiencing Cypress issue #22428. Use cypress-on-fix to register the plugins:

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  e2e: {
    // baseUrl, etc
    supportFile: false,
    fixturesFolder: false,
    setupNodeEvents(cypressOn, config) {
      const on = require('cypress-on-fix')(cypressOn)
      // use "on" to register plugins, for example
      // https://github.com/bahmutov/cypress-split
      require('cypress-split')(on, config)
      // https://github.com/bahmutov/cypress-watch-and-reload
      require('cypress-watch-and-reload/plugins')(on, config)
      // https://github.com/bahmutov/cypress-code-coverage
      require('@bahmutov/cypress-code-coverage/plugin')(on, config)

      // IMPORTANT: return the config object
      return config
    },
  },
})

TypeScript

Types are in src/types.d.ts file. You should be able to import the config function in your TS config file.

import { defineConfig } from 'cypress'
import cypressSplit from 'cypress-split'

module.exports = defineConfig({
  e2e: {
    // baseUrl, etc
    supportFile: false,
    fixturesFolder: false,
    setupNodeEvents(on, config) {
      cypressSplit(on, config)
      // IMPORTANT: return the config object
      return config
    },
  },
})

Multiple plugins

If you are using many Cypress plugins (for example my plugins covered in the Cypress Plugins course), you might notice that only the last plugin really works. This is due to a bug, and you can work around it using cypress-on-fix.

Your specPattern list

If you set your own specs via config.specPattern, just do it before using the plugin to split them.

setupNodeEvents(on, config) {
  // user sets their own custom specPattern list of specs
  // make sure the list of specs is relative to the folder
  // with the Cypress config file!
  config.specPattern = [
    '../cypress/e2e/spec-c.cy.js',
    '../cypress/e2e/spec-d.cy.js',
    '../cypress/e2e/spec-e.cy.js',
  ]
  cypressSplit(on, config)
  // IMPORTANT: return the config object
  return config
},

Small print

Author: Gleb Bahmutov <[email protected]> © 2023

License: MIT - do anything with the code, but don't blame me if it does not work.

Support: if you find a problem, open an issue in this repository. Consider sponsoring my open-source work.

cypress-split's People

Contributors

anlambert avatar bahmutov avatar baune8d avatar luka-bacic avatar muriukialex avatar parkuman avatar pavelloz avatar renovate[bot] avatar tommy-anderson avatar vallme2003 avatar vincentgarreau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

cypress-split's Issues

Why would cypress not be found in the 2nd and 3rd splits on Gitlab

In the example pipeline job 1/3 was passing but 2/3 & 3/3 were failing with "Your configFile is invalid: /cypress.config.js It threw an error when required, check the stack trace below:Error: Cannot find module 'cypress'" I updated the docker image from cypress/base:16.14.2-slim to cypress/browsers:node14.19.0-chrome100-ff99-edge and all 3 now work.

image

spec="spec1,spec2,spec3" under --env option fails with "Cannot parse as valid JSON" error

Hi!

npx cypress run --env split=true,spec="spec1,spec2,spec3" or npx cypress run --env spec="spec1,spec2,spec3" fails:
image

The same about npx cypress run --env split=2,splitIndex=0,spec="spec1,spec2,spec3"

It works fine with 1 spec, and I didn't succeed to find a syntax which allows to pass more than one spec.
I've seen there are examples like cypress run --env flags='{"feature-a":true,"feature-b":false}' in documentation, but didn't found examples like mine.

I'm wondering if there is a way to use it as described in ReadMe?

Thank you!

Add publish-summary field in GitHub Action usgae

Request -
Can you add a publish-summary field, or use the existing value from cypress-io/github-action to disabled the summary report?

I am adding a custom report after each run, and currently cypress-split is adding a summary above it, even though I set publish-summary to false.

Can't seem to get this to work with Cypress 12.16.0 and Typescript

I am trying to run this with the following

Cypress 12.16.0
Typescript
Cypress-Cucumber-PreProcessor

Am receiving the following error

The error was thrown while executing your e2e.setupNodeEvents() function:
TypeError: (0 , cypress_split_1.cypressSplit) is not a function

What am I doing wrong?

Issue with cucumber feature specs

Hi Gled,

We have issue with feature specs.

Steps:

  1. Add cucumber to your project: https://www.npmjs.com/package/cypress-cucumber-preprocessor
  2. Open folder in e2e with the name features
  3. Add feature file with the name for eg Header.feature and with the content

Feature: 001 Header
I want to check the header

Scenario: Header Logo
Given I navigate to 'https://www.google.com/'
Then Logo is visible


Screenshot 2023-02-08 at 13 49 29
Screenshot 2023-02-08 at 13 50 06

Run cypress-io/github-action@v5
/usr/local/bin/npm ci
npm WARN deprecated [email protected]: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
npm WARN deprecated [email protected]: This package is now published under @cucumber/gherkin
npm WARN deprecated [email protected]: This package is now published under @cucumber/cucumber-expressions
npm WARN deprecated [email protected]: This package is now published under @cucumber/cucumber-expressions
npm WARN deprecated [email protected]: Cucumber is publishing new releases under @cucumber/cucumber
npm WARN deprecated [email protected]: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.

added 785 packages, and audited 786 packages in 25s

94 packages are looking for funding
run npm fund for details

4 high severity vulnerabilities

Some issues need review, and may require choosing
a different dependency.

Run npm audit for details.
/usr/local/bin/npx cypress cache list
┌─────────┬────────────┐
│ version │ last used │
├─────────┼────────────┤
│ 12.5.1 │ 6 days ago │
└─────────┴────────────┘
/usr/local/bin/npx cypress verify

[STARTED] Task without title.
[SUCCESS] Task without title.
/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/cs-qa-automation/cs-qa-automation --files-from manifest.txt --use-compress-program zstdmt
Failed to save: Unable to reserve cache with key npm-linux-x64-0f1b354c96bd8ecc11cfcee398e6b15fcd0f5304981f726fd1d69f1bd0cfe453f56e601e3e99dd3813a1d288ca63355b901f0286ed4b57f7b924964afe1a3139, another job may be creating this cache. More details: Cache already exists. Scope: refs/heads/main, Key: npm-linux-x64-0f1b354c96bd8ecc11cfcee398e6b15fcd0f5304981f726fd1d69f1bd0cfe453f56e601e3e99dd3813a1d288ca63355b901f0286ed4b57f7b924964afe1a3139, Version: 04d00cc68e25ee34fd8b04095d0a46a28244d98af53e6925e47ed311d487b1d6
/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/runner/work/cs-qa-automation/cs-qa-automation --files-from manifest.txt --use-compress-program zstdmt
Failed to save: Unable to reserve cache with key cypress-linux-x64-0f1b354c96bd8ecc11cfcee398e6b15fcd0f5304981f726fd1d69f1bd0cfe453f56e601e3e99dd3813a1d288ca63355b901f0286ed4b57f7b924964afe1a3139, another job may be creating this cache. More details: Cache already exists. Scope: refs/heads/main, Key: cypress-linux-x64-0f1b354c96bd8ecc11cfcee398e6b15fcd0f5304981f726fd1d69f1bd0cfe453f56e601e3e99dd3813a1d288ca63355b901f0286ed4b57f7b924964afe1a3139, Version: 1955096f8dd018efdf62615d0a27779c95e9b0287a6a71bc182356f3b1a36196
[2123:0208/122921.036493:ERROR:gpu_memory_buffer_support_x11.cc(44)] dri3 extension not supported.
Couldn't find tsconfig.json. tsconfig-paths will be skipped
cypress-split: there are 17 found specs
cypress-split: split 0 of 4
k spec


1 cypress/e2e/features/00_Common/001_Header.feature
2 cypress/e2e/features/00_Common/002_Footer.feature
3 cypress/e2e/features/00_Common/003_Percy_Screenshots.feature
4 cypress/e2e/features/02_Cookies_Policy/020_Cookie_Bar.feature
5 cypress/e2e/features/02_Cookies_Policy/021_Content.feature

Your configFile threw an error from: /home/runner/work/cs-qa-automation/cs-qa-automation/cypress.config.js

The error was thrown while executing your e2e.setupNodeEvents() function:

Error: ENOENT: no such file or directory, open './undefined.json'
at Object.openSync (node:fs:585:3)
at readFileSync (node:fs:453:35)
at setupNodeEvents (/home/runner/work/cs-qa-automation/cs-qa-automation/cypress.config.js:16:20)
at /home/runner/.cache/Cypress/12.5.1/Cypress/resources/app/node_modules/@packages/server/lib/plugins/child/run_plugins.js:118:14
at tryCatcher (/home/runner/.cache/Cypress/12.5.1/Cypress/resources/app/node_modules/bluebird/js/release/util.js:16:23)
at Function.Promise.attempt.Promise.try (/home/runner/.cache/Cypress/12.5.1/Cypress/resources/app/node_modules/bluebird/js/release/method.js:39:29)
at RunPlugins.load (/home/runner/.cache/Cypress/12.5.1/Cypress/resources/app/node_modules/@packages/server/lib/plugins/child/run_plugins.js:115:9)
at RunPlugins.runSetupNodeEvents (/home/runner/.cache/Cypress/12.5.1/Cypress/resources/app/node_modules/@packages/server/lib/plugins/child/run_plugins.js:276:10)
at EventEmitter. (/home/runner/.cache/Cypress/12.5.1/Cypress/resources/app/node_modules/@packages/server/lib/plugins/child/run_require_async_child.js:185:22)
at EventEmitter.emit (node:events:527:28)
at EventEmitter.emit (node:domain:475:12)
at process. (/home/runner/.cache/Cypress/12.5.1/Cypress/resources/app/node_modules/@packages/server/lib/plugins/util.js:33:22)
at process.emit (node:events:527:28)
at process.emit (node:domain:475:12)
at process.emit.sharedData.processEmitHook.installedValue [as emit] (/home/runner/.cache/Cypress/12.5.1/Cypress/resources/app/node_modules/@cspotcode/source-map-support/source-map-support.js:745:40)
at emit (node:internal/child_process:938:14)
at processTicksAndRejections (node:internal/process/task_queues:84:21)
Test run failed, code 1
More information might be available above
Cypress module has returned the following error message:
Could not find Cypress test run results
Error: Could not find Cypress test run results

Running cypress-split on BitBucket pipeline

I'm having issues trying to split my tests through BitBucket pipelines. Cypress-split is able to identify all the specs and split them properly using the environment variables SPLIT_INDEX and SPLIT, however each parallel step in bb pipelines still tries to run all of the tests when the run starts. Can you please help me troubleshoot this? Thank you

Here's what a step will look like:

cypress-split: there are 30 found specs
cypress-split: split 1 of 10
k spec


1 e2e/client/{testname}_4.cy.ts
2 e2e/client/{testname}_5.ts
3 e2e/client/{testname}_6.cy.ts

(Run Starting)
Running: {testname}_1.cy.ts (1 of 30)

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

circleci
.circleci/config.yml
  • cypress 2.2.0
github-actions
.github/workflows/badges.yml
  • actions/checkout v4
  • stefanzweifel/git-auto-commit-action v5
  • ubuntu 22.04
.github/workflows/ci.yml
  • bahmutov/gh-build-matrix v1.0.1
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • bahmutov/cypress-workflows v2
  • bahmutov/cypress-workflows v2
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cypress-io/github-action v6
  • actions/checkout v4
  • cycjimmy/semantic-release-action v4
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
npm
package.json
  • @actions/core ^1.10.0
  • arg ^5.0.2
  • console.table ^0.10.0
  • debug ^4.3.4
  • fast-shuffle ^6.1.0
  • find-cypress-specs 1.43.4
  • humanize-duration ^3.28.0
  • ava ^6.1.0
  • cypress ^13.3.0
  • prettier ^3.0.3
  • react ^18.2.0
  • react-dom ^18.2.0
  • semantic-release ^24.0.0
  • vite ^5.0.0
nvm
.nvmrc
  • node 20.14.0

  • Check this box to trigger a request for Renovate to run again on this repository

I noticed that one of the container job fails as cypress-split tries to recognise all the tests under cypress/e2e (error message "Can't run because no spec files were found."). However, I have a custom script that should run the spec files under one folder 'regression-tests' i.e cypress/e2e/regression-tests)

Hi,

I have the following folder structure in cypress-
cypress/e2e

  1. folder1 is all-tests (has 2 feature files)
  2. folder2 is regression-tests (has 4 feature files)

My custom script is to run the tests in one of the folder "cypress run -s cypress/e2e/regression-tests --env ENV=qa -e TAGS='@regression".

I am using cypress-split plugin for parallelisation using 3 containers however the container 1 job fails with error message "Can't run because no spec files were found." I have added the logs from the container job that failed.

> [email protected] cy:qa:regression
> cypress run -s cypress/e2e/regression-tests --env ENV=qa -e TAGS='@regression'



DevTools listening on ws://127.0.0.1:46265/devtools/browser/3e19e806-dcac-4264-af7f-15a6b3714a43
[1984:0627/090230.104157:ERROR:gpu_memory_buffer_support_x11.cc(44)] dri3 extension not supported.
Couldn't find tsconfig.json. tsconfig-paths will be skipped
cypress-split: there are 6 found specs
cypress-split: split 0 of 3
k  spec                                      
---------------------------------------------
1  cypress/e2e/all-tests/duckduckgo.feature  
2  cypress/e2e/all-tests/other-search.feature

Can't run because no spec files were found.

We searched for specs matching this glob pattern:

  > /home/runner/work/spring-qa-cypress/spring-qa-cypress/cypress/e2e/regression-tests
Error: The process '/usr/local/bin/npm' failed with exit code 1

My question is why the container 1 job tries to find the specs files in the folder that is not part of the custom script? Any help is appreciated. Thank you :)

cypress-split: there are 0 found specs

Hi! I faced the issue with finding the specs. cypress-split found 0 of them.

❯ DEBUG=cypress-split,find-cypress-specs SPLIT=1 SPLIT_INDEX=0 cypress run --e2e --config-file tests/cypress/cypress.config.ts --browser chrome --reporter teamcity

DevTools listening on ws://127.0.0.1:57041/devtools/browser/25c7f080-b912-404f-a87c-c51eb6213e55
  cypress-split Cypress config env +0ms
  cypress-split {
  cypress-split   'cypress-plugin-snapshots': '{"autoCleanUp":false,"autopassNewSnapshots":true,"diffLines":3,"excludeFields":[],"formatJson":true,"ignoreExtraArrayItems":false,"ignoreExtraFields":false,"imageConfig":{"createDiffImage":true,"resizeDevicePixelRatio":true,"threshold":0.1,"thresholdType":"percent"},"normalizeJson":true,"prettier":true,"prettierConfig":{"html":{"parser":"html","tabWidth":2,"endOfLine":"lf"}},"screenshotConfig":{"blackout":[],"capture":"fullPage","clip":null,"padding":null,"disableTimersAndAnimations":true,"log":false,"scale":false,"timeout":30000},"serverEnabled":false,"serverHost":"localhost","serverPort":2121,"token":"xxx-token-xxx","updateSnapshots":false,"backgroundBlend":"difference","name":""}'
  cypress-split } +1ms
  find-cypress-specs finding specs of type e2e +0ms
  find-cypress-specs Cypress version 13.3.0 +0ms
  find-cypress-specs treating options as Cypress version 13 +0ms
  find-cypress-specs config has "e2e" property, treating as Cypress v10+ +1ms
  find-cypress-specs findCypressSpecsV10 +0ms
  find-cypress-specs options v10 { specPattern: 'tests/cypress/integration/**/*.spec.ts*', excludeSpecPattern: '**/*.spec.ts.snap' } +0ms
  find-cypress-specs globby options tests/cypress/integration/**/*.spec.ts* { sort: true, ignore: [ '**/*.spec.ts.snap' ], absolute: true } +0ms
  find-cypress-specs found 0 file(s) [] +6ms
  find-cypress-specs ignore patterns [ '**/*.spec.ts.snap' ] +0ms
  find-cypress-specs filtered 0 specs +0ms
  find-cypress-specs  +0ms
cypress-split: there are 0 found specs

I read that cypress-split is based on find-cypress-specs, so I ran it separately from the same dir and it found all the specs:

❯ DEBUG=find-cypress-specs CYPRESS_CONFIG_FILE=tests/cypress/cypress.config.ts npx find-cypress-specs

  find-cypress-specs arguments { _: [] } +0ms
  find-cypress-specs found file tests/cypress/cypress.config.ts +0ms
  find-cypress-specs loading Cypress config from /Users/denis.domanskii/git/my-app/tests/cypress/cypress.config.ts +54ms
  find-cypress-specs returning default export as config from ./tests/cypress/cypress.config.ts +619ms
  find-cypress-specs finding specs of type e2e +0ms
  find-cypress-specs treating options as Cypress version 10 +0ms
  find-cypress-specs config has "e2e" property, treating as Cypress v10+ +0ms
  find-cypress-specs findCypressSpecsV10 +1ms
  find-cypress-specs options v10 { specPattern: 'tests/cypress/integration/**/*.spec.ts*', excludeSpecPattern: '**/*.spec.ts.snap' } +0ms
  find-cypress-specs globby options tests/cypress/integration/**/*.spec.ts* { sort: true, ignore: [ '**/*.spec.ts.snap' ], absolute: false } +0ms
  find-cypress-specs found 38 file(s) [ 'tests/cypress/integration/anchors.spec.ts', 'tests/cypress/integration/basic-types.spec.ts', ... ] +7ms
  find-cypress-specs ignore patterns [ '**/*.spec.ts.snap' ] +10ms
  find-cypress-specs filtered 38 specs +2ms
  find-cypress-specs tests/cypress/integration/anchors.spec.ts
  find-cypress-specs tests/cypress/integration/basic-types.spec.ts
  ...

In both scenarios it definitely reads the custom config file, because specPattern is correct. But something is wrong in cypress-split <-> find-cypress-specs interaction. I tried cypress-on-fix, but nothing changed. Also I tried to explicitly pass CYPRESS_CONFIG_FILE env variable to cypress, but nothing change too.

Running cypress-split with a matrix for both browsers + multiple containers

Hey,

This is a great piece of work, I want to acknowledge how handy this is 👍

I was hoping to see if anyone else was attempting to figure this out:

for eg.

    strategy:
      fail-fast: false
      matrix:
        containers: [1, 2, 3]
        browser: [chrome, edge]

if i want to run parallel containers, but also multiple browsers, it appears to act in an unexpected way.

In the above e.g, all of the tests are split across all instances of the browsers + containers.

My desired behaviour is to try and get 3 containers for chrome, 3 containers for edge and have the full test suite run across both browsers.

If anyone has any ideas, I'd be super appreciative 👍

Tests failing when I use split | Github Actions

Hi @bahmutov I'm seeing failed tests when i run cypress tests using cypress split like this:

uses: bahmutov/cypress-workflows/.github/workflows/split.yml@v2
with:
  nComponent: 4

Tests are running perfectly fine but sometimes some of them fails with this error message:

App test
  "before each" hook for "should mount component":
 TypeError: Cannot destructure property 'data' of 'undefined' as it is undefined.

This is how my App test looks like:

import { RouterTestingModule } from '@angular/router/testing';
import { CookieModule } from 'ngx-cookie';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { AppComponent } from './app.component';

describe('App test', () => {
  it('should mount component', () => {
    cy.mount(AppComponent, {
      imports: [
        RouterTestingModule,
        CookieModule.forRoot(),
        MatSnackBarModule,
        HttpClientTestingModule,
      ],
    });
  });
});

As you can see it is just basic smoke testing of app component. Sometimes it fails here, sometimes on another component test, sometimes it doesn't fails.

Do you know why these errors are occurring and can I do something to prevent them?

Using cypress-split locally And using it in combination with Sorry Cypress

Hello,

As you might know there is an alternative to cypress cloud, which is Current Or Sorry Cypress which is free. Where we can already run tests in parallel but can we mix Split with the Sorry Cypress? Also I used this in my CLI but it throws me multiple error, is this dependent on each other like the mocks that might have been used first etc.

npx cypress run --env split=3,splitIndex=0

Question:How can i run if i am using SpecPattern variable in Cypress.config file

here is the my cypress.config script.

const { defineConfig } = require("cypress");

module.exports = defineConfig({
projectId: '9iyncm',
e2e: {
//baseUrl:"https://app.paismo.com",
baseUrl:"https://app-stage.paismo.com",
testIsolation: false,
viewportWidth: 1660,
viewportHeight: 1000,
setupNodeEvents(on, config) {
config.specPattern = [
'cypress/e2e/Login.cy.js',
'cypress/e2e/Employee.cy.js',
'cypress/e2e/My-Profile-edit/Profile.cy.js',
'cypress/e2e/My-Profile-edit/Employment.cy.js',
'cypress/e2e/My-Profile-edit/Payroll-Preferences.cy.js',
'cypress/e2e/My-Profile-edit/Offboarding.cy.js',
'cypress/e2e/Full-Employee-edit/Profile.cy.js',
'cypress/e2e/Full-Employee-edit/Employment.cy.js',
'cypress/e2e/Full-Employee-edit/Payroll-Preferences.cy.js',
'cypress/e2e/Full-Employee-edit/Offboarding.cy.js',
'cypress/e2e/Schedules, Timesheets & Leave/Time-Off-Request.cy.js',
'cypress/e2e/Settings-/Departments-Work Locations.cy.js',
'cypress/e2e/Settings-/Work-Scdules-PTO.cy.js',
'cypress/e2e/Payroll/Run-Payroll.cy.js',

  ]
  // IMPORTANT: need to return the changed config
  // so Cypress knows about your changes
  return config
},

experimentalRunAllSpecs: true, // implement node event listeners here
defaultCommandTimeout: 10000,

},

// "experimentalSessionAndOrigin": true,

});

(1 of 2) Node 18 shows no specs to run with unknown spec name = empty-3-of-4.cy.js

Hi @bahmutov I'm raising 2 bugs that may or may not be related to each other.

I have created an example repo here: https://github.com/bennymeade/cypress-split-node-18-config-file/
Which is Node 18, yarn, typescript and cypress-split with 2 containers based.

In my workflow for Node 18 steps 'Run desktop tests' see here: https://github.com/bennymeade/cypress-split-node-18-config-file/actions/runs/4963303007/jobs/8882400118#step:5:80

Run command: yarn cypress run --browser chrome

  │ Cypress:        12.12.0                                                                        │
  │ Browser:        Chrome 113 (headless)                                                          │
  │ Node Version:   v18.16.0 (/opt/hostedtoolcache/node/18.16.0/x64/bin/node)                      │
  │ Specs:          1 found (empty-3-of-4.cy.js)                                                   │
  │ Searched:       /tmp/empty-3-of-4.cy.js     

No specs are found or run, but the build step still completes as success.

image

This is working fine on Node 16 see here: https://github.com/bennymeade/cypress-split-node-18-config-file/actions/runs/4963303007/jobs/8882400034#step:5:84

TeamCity: Invalid chunk index 1 vs all chunks 1

It looks like cypress-split can't handle the situation when there is only 1 chunk and chunk index is 1. I understand that it has no sense, but I really need to support such a scenario (e.g. only 1 build agent is free), and expect that all specs will be executed as usual.

Log:

[19:07:23 ] cypress-split: there are 0 found specs
[19:07:23 ] cypress-split: chunk 2 of 1
[19:07:23 ] Your configFile threw an error from: /mnt/agent/work/bb494e5cdc59eb2f/tests/cypress/cypress.config.ts
[19:07:23 ] 
[19:07:23 ] The error was thrown while executing your e2e.setupNodeEvents() function:
[19:07:23 ] 
[19:07:23 ] Error: Invalid chunk index 1 vs all chunks 1
[19:07:23 ]     at getChunk (/mnt/agent/work/bb494e5cdc59eb2f/node_modules/cypress-split/src/chunk.js:47:11)
[19:07:23 ]     at cypressSplit (/mnt/agent/work/bb494e5cdc59eb2f/node_modules/cypress-split/src/index.js:106:24)
[19:07:23 ]     at module.exports (/mnt/agent/work/bb494e5cdc59eb2f/tests/cypress/plugins/index.js:8:3)
[19:07:23 ]     at setupNodeEvents (/mnt/agent/work/bb494e5cdc59eb2f/tests/cypress/cypress.config.ts:21:43)
[19:07:23 ]     at /mnt/agent/work/bb494e5cdc59eb2f/node_modules/cypress_cache/13.3.0/Cypress/resources/app/node_modules/@packages/server/lib/plugins/child/run_plugins.js:122:14
[19:07:23 ]     at tryCatcher (/mnt/agent/work/bb494e5cdc59eb2f/node_modules/cypress_cache/13.3.0/Cypress/resources/app/node_modules/bluebird/js/release/util.js:16:23)
[19:07:23 ]     at Function.Promise.attempt.Promise.try (/mnt/agent/work/bb494e5cdc59eb2f/node_modules/cypress_cache/13.3.0/Cypress/resources/app/node_modules/bluebird/js/release/method.js:39:29)
[19:07:23 ]     at RunPlugins.load (/mnt/agent/work/bb494e5cdc59eb2f/node_modules/cypress_cache/13.3.0/Cypress/resources/app/node_modules/@packages/server/lib/plugins/child/run_plugins.js:119:9)
[19:07:23 ]     at RunPlugins.runSetupNodeEvents (/mnt/agent/work/bb494e5cdc59eb2f/node_modules/cypress_cache/13.3.0/Cypress/resources/app/node_modules/@packages/server/lib/plugins/child/run_plugins.js:59:17)
[19:07:23 ]     at EventEmitter.<anonymous> (/mnt/agent/work/bb494e5cdc59eb2f/node_modules/cypress_cache/13.3.0/Cypress/resources/app/node_modules/@packages/server/lib/plugins/child/run_require_async_child.js:185:22)
[19:07:23 ]     at EventEmitter.emit (node:events:514:28)
[19:07:23 ]     at EventEmitter.emit (node:domain:489:12)
[19:07:23 ]     at process.<anonymous> (/mnt/agent/work/bb494e5cdc59eb2f/node_modules/cypress_cache/13.3.0/Cypress/resources/app/node_modules/@packages/server/lib/plugins/util.js:33:22)
[19:07:23 ]     at process.emit (node:events:514:28)
[19:07:23 ]     at process.emit (node:domain:489:12)
[19:07:23 ]     at process.emit.sharedData.processEmitHook.installedValue [as emit] (/mnt/agent/work/bb494e5cdc59eb2f/node_modules/cypress_cache/13.3.0/Cypress/resources/app/node_modules/@cspotcode/source-map-support/source-map-support.js:745:40)
[19:07:23 ]     at emit (node:internal/child_process:951:14)
[19:07:23 ]     at processTicksAndRejections (node:internal/process/task_queues:83:21)

Confirm this plugin works with wildcard spec parameter

- name: Run bonus tests 🧪
  # https://github.com/cypress-io/github-action
  uses: cypress-io/github-action@v4
  with:
    spec: 'cypress/integration/bonus*.js'
  env:
    SPLIT: ${{ strategy.job-total }}
    SPLIT_INDEX: ${{ strategy.job-index }}

cypress-split: split 0 of 3

I have a github action like below form following the guides and noticed in the output of the split it says:
Agent 1: 'cypress-split: split 0 of 3'
Agent 2: 'cypress-split: split 1 of 3'
Agent 3: 'cypress-split: split 1 of 3'

Expected split 1 of 3, split 2 of 3, split 3 of 3

name: Cypress Tests on: push: branches: - main schedule: - cron: "0 13 * * 0" jobs: build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: containers: [1, 2, 3] steps: - name: Checkout repo uses: actions/checkout@v2 - name: Run Cypress tests uses: cypress-io/github-action@v5 env: SPLIT: ${{ strategy.job-total }} SPLIT_INDEX: ${{ strategy.job-index }}

Add a feature to split based on the tags

First of all, thank you for this wonderful plugin.

Addition to splitting all the features files in the integration folder, adding a filter to it using tags will reduce the files for execution.

In our project, we have more than 250 cases. Kind of huge of feature files. We have split the CI Jobs based on the tags and running it. But that too take a more than 2 hours to complete the execution. If this plugin provide the tags config, then we can split even more in running and get the results a bit sooner.

Am thinking of some thing like below.

npx cypress run -e tags=@test,split=true

(2 of 2) Using `--config-file` the tests are not running in parallel

Hi @bahmutov I'm seeing this on both Node 16 and Node 18

Same repo here: https://github.com/bennymeade/cypress-split-node-18-config-file/

Which is Node 16 or Node 18, yarn, typescript, cypress-split with 2 containers and using a different --config in cypress/configs/cypress.mobile.config.ts based.

The mobile tests are using command: $ cypress run --browser chrome --config-file cypress/configs/cypress.mobile.config.ts

Node 16 example 'Run mobile tests': https://github.com/bennymeade/cypress-split-node-18-config-file/actions/runs/4963303007/jobs/8882400034#step:6:105

Node 18 example 'Run mobile tests': : https://github.com/bennymeade/cypress-split-node-18-config-file/actions/runs/4963303007/jobs/8882400201#step:6:105

Note that there is no pre run info about the cypress-split details, as expected like this:

cypress-split: there are 2 found specs
cypress-split: split 3 of 4
image image

ReferenceError: require is not defined error when opening cypress runner with cypress-split

Hi,

This error appears when I open the cypress runner after installing cypress split.

Your configFile is invalid: /home/andisan/Work/tangram/e2e-tests/ui-tests/cypress.config.js

It threw an error when required, check the stack trace below:

ReferenceError: require is not defined
    at file:///home/andisan/Work/tangram/e2e-tests/ui-tests/cypress.config.js:5:22
    at ModuleJob.run (internal/modules/esm/module_job.js:152:23)
    at async Loader.import (internal/modules/esm/loader.js:166:24)
    at async loadFile (/home/andisan/.cache/Cypress/10.2.0/Cypress/resources/app/node_modules/@packages/server/lib/plugins/child/run_require_async_child.js:106:14)
    at async EventEmitter.<anonymous> (/home/andisan/.cache/Cypress/10.2.0/Cypress/resources/app/node_modules/@packages/server/lib/plugins/child/run_require_async_child.js:116:32)

cypress.config.js:

import { defineConfig } from 'cypress';
const cypressSplit = require('cypress-split');

export default defineConfig({
  e2e: {
    defaultCommandTimeout: 30000,
    requestTimeout: 15000,
    responseTimeout: 60000,
    chromeWebSecurity: false,
    video: false,
    experimentalSessionAndOrigin: true,
    setupNodeEvents(on, config) {
      cypressSplit(on, config)
      return config;
    },
  },
});

cypress version: 10.2.0
cypress-split version: 1.2.0

`Webpack Compilation Error` when using `paths` aliases in Typescript (running `empty-4-of-4.cy.js` spec)

Hi @bahmutov, thank you very much for this project!

Could you please suggest how to make cypress-split work when using paths aliases in tsconfig?

i.e. given the /cypress/tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["es5", "dom"],
    "types": ["cypress", "@testing-library/cypress", "node"],
    "baseUrl": "./",
    "paths": {
      "#/*": ["../src/*"],
      "#tests/*": ["../tests/*"]
    }
  },
  "include": ["**/*.ts"]
}

setting up running the cypress-split per readme, when having only 3 spec files:
(running on local Mac OS machine)

# errors out with 
# Error: Webpack Compilation Error
# Module not found: Error: Can't resolve '#tests/mock-rest-api-server' in '/Users/…/…/…/…/…/cypress/support'
# …
# The spec file that runs is `empty-4-of-4.cy.js`

SPLIT=4 SPLIT_INDEX=3 yarn cypress run

and running the following succeds:

# runs succesfully
# The spec file that runs is `notifications.cy.ts` 
SPLIT=4 SPLIT_INDEX=1 yarn cypress run

Additional info:

  • If I change the source code of node_modules/cypress-split/src/index.js to use empty-spec.cy.ts and run SPLIT=4 SPLIT_INDEX=3 yarn cypress run again, I get more info on the error:
  Running:  empty-4-of-4.cy.ts                                                              (1 of 1)

Oops...we found an error preparing this test file:

  > ../../../../../../var/folders/p0/npm2s71j2bz2s8pm770p55700000gp/T/empty-4-of-4.cy.ts

The error was:

Error: Webpack Compilation Error
[tsl] ERROR
      TS18002: The 'files' list in config file 'tsconfig.json' is empty.

Support for component tests

Finally got this working in our monorepo only to realize it doesn't work for Cypress component tests.

Is there any reason for that? Would be great to add support for them.

Thanks for making this library!

does cypress fail-fast cypress plugin work alongside cypress split

my cypress.config.ts has the below config values

   e2e: {
    setupNodeEvents(on, config) {
      on('task', {
        'load:tcValidations': loadValidations,
      });
      /* eslint-disable @typescript-eslint/no-var-requires */
      require('cypress-fail-fast/plugin')(on, config);
      cypressSplit(on, config);
      return config;
    },
    baseUrl: 'http://localhost:3000',
    testIsolation: true,
    specPattern: 'cypress/e2e/test_containers/*.spec.{js,jsx,ts,tsx}',
  },

I have been able to make the fail fast work if i only include fail fast as mentioned in this documentation
https://www.npmjs.com/package/cypress-fail-fast

if I include the below code I'm unable to get it working
cypressSplit(on, config);

any leads on this ?

question: return config two values

Hello Gleb, I have a question, how do I return 2 values? I need to return the config and the fs.readJSON, I tried to separate the values ​​with a comma but it didn't work.

image

I tried this way:

return fs.readJson(path.resolve(envs/cypress.${file}.json)), config

Could not find spec results - empty Summary

Seeing following in the Cypress run: Could not find spec results for cypress/e2e/admin/settings.cy.ts

This is the summary page:
image

The command that is being run:
"cy:ui": "npx cypress run --env grepTags=regression --spec 'cypress/e2e/**/*'",

It looks like it is still grabbing the API tests, even when specified the specific spec

My Github action yaml:

jobs:
  e2e-ui:
    name: e2e UI Tests
    runs-on: ubuntu-22.04
    strategy:
      fail-fast: false
      matrix:
        containers: [1, 2, 3, 4]
    defaults:
      run:
        working-directory: packages/e2e

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Run split Cypress tests 🧪
        uses: cypress-io/github-action@v5
        with:
          command: npm run cy:ui
        env:
          SPLIT: ${{ strategy.job-total }}
          SPLIT_INDEX: ${{ strategy.job-index }}

      - name: Generate Report
        if: failure()
        run: npm run cy:report

      - name: Upload to S3 bucket
        if: failure()
        uses: shallwefootball/s3-upload-action@master
        id: S3
        with:
          aws_key_id: ${{ secrets.AWS_KEY_ID }}
          aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws_bucket: ${{ vars.AWS_BUCKET_NAME }}
          source_dir: './packages/e2e/cypress/reports/htmlReport'

      - name: Get Cypress data
        if: failure()
        run: |
          echo TOTAL_TESTS=$(jq '.stats.tests' ./cypress/reports/htmlReport/report.json) >> $GITHUB_ENV
          echo TEST_PASSED=$(jq '.stats.passes' ./cypress/reports/htmlReport/report.json) >> $GITHUB_ENV
          echo TEST_FAILED=$(jq '.stats.failures' ./cypress/reports/htmlReport/report.json) >> $GITHUB_ENV
          echo REPORT_URL="${{ vars.AWS_S3_BUCKET_URL }}/${{steps.S3.outputs.object_key}}/report.html" >> $GITHUB_ENV

      - name: Slack Failure Notification
        if: failure()
        uses: rtCamp/action-slack-notify@v2
        env:
          SLACK_CHANNEL: de5-status-tests
          SLACK_COLOR: failure
          SLACK_MESSAGE: "Tests: ${{ env.TOTAL_TESTS }}\n Passed: ${{ env.TEST_PASSED }}\nFailures: ${{ env.TEST_FAILED }} \n Report: ${{ env.REPORT_URL }}"
          SLACK_TITLE: DEKN Cypress tests failed
          SLACK_USERNAME: cypress-bot
          SLACK_WEBHOOK: ${{ vars.SLACK_WEBHOOK }}

Cypress runs failing in Github Actions. Threw 'TypeError: patterns.reduce is not a function error' under cypressSplit(on, config)

Hi, thank you so much for creating cypress-split. It's a very helpful tool.

It seems that a few days ago, my cypress job runs in Github Actions are failing with the error below. No changes were done from my side. I've tried increasing cypress version and such but no luck. Could you help to determine what might've caused this issue? I've also included my cypress.config.js file below for reference. thank you.

The error was thrown while executing your e2e.setupNodeEvents() function:

TypeError: patterns.reduce is not a function
    at Object.expandPatternsWithBraceExpansion (/home/runner/work/AutomationCypress/node_modules/fast-glob/out/utils/pattern.js:131:21)
    at processPatterns (/home/runner/work/AutomationCypress/node_modules/fast-glob/out/managers/tasks.js:27:34)
    at Object.generate (/home/runner/work/AutomationCypress/node_modules/fast-glob/out/managers/tasks.js:7:20)
    at getWorks (/home/runner/work/AutomationCypress/node_modules/fast-glob/out/index.js:91:31)
    at AsyncFunction.sync (/home/runner/work/AutomationCypress/node_modules/fast-glob/out/index.js:23:23)
    at AsyncFunction.module.exports.sync (/home/runner/work/AutomationCypress/node_modules/globby/index.js:151:42)
    at findCypressSpecsV10 (/home/runner/work/AutomationCypress/node_modules/find-cypress-specs/src/index.js:150:24)
    at findCypressSpecs (/home/runner/work/AutomationCypress/node_modules/find-cypress-specs/src/index.js:233:21)
    at getSpecs (/home/runner/work/AutomationCypress/node_modules/find-cypress-specs/src/index.js:210:10)
    at cypressSplit (/home/runner/work/AutomationCypress/node_modules/cypress-split/src/index.js:94:15)
    at setupNodeEvents (/home/runner/work/AutomationCypress/cypress.config.js:11:3)

cypress.config.js file:

const { defineConfig } = require("cypress")
const createBundler = require("@bahmutov/cypress-esbuild-preprocessor")
const cucumberPreprocessor = require("@badeball/cypress-cucumber-preprocessor")
const createEsbuildPlugin = require("@badeball/cypress-cucumber-preprocessor/esbuild")
const cypressSplit = require('cypress-split')

async function setupNodeEvents(cypressOn, config) {
  const on = require('cypress-on-fix')(cypressOn)
  // This is required for the preprocessor to be able to generate JSON reports after each run, and more,
  await cucumberPreprocessor.addCucumberPreprocessorPlugin(on, config)
  cypressSplit(on, config)

  on(
    "file:preprocessor", 
      createBundler({
        plugins: [createEsbuildPlugin.default(config)],
      })
  );

  on('task', {
    log(message) {
      console.log(message)
      return null
    }
  })

  // Make sure to return the config object as it might have been modified by the plugin.
  return config
}

module.exports = defineConfig({
  e2e: {
    specPattern: "**/*.feature",
    supportFile: false,
    setupNodeEvents,
    experimentalSessionAndOrigin: true,
    chromeWebSecurity: false
    },
});

version:
"cypress-split": "^1.3.12"
"cypress": "^11.2.0"

related github actions versions:
cypress-io/github-action@v5
runs-on: ubuntu-22.04

Split based on running time

Would it be possible to split the tests not based on name, but based on how long they run? Such that all the parallel machines finish at approximately the same time?

At this point, we have a fairly uneven distribution of tests between our runners.

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.