Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add skipped specs filter #226

Merged
merged 3 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,28 @@ jobs:
SPLIT_INDEX1: 1
DEBUG: 'cypress-split'

test-skipped-specs:
runs-on: ubuntu-22.04
steps:
- name: Checkout 🛎
uses: actions/checkout@v4

- name: Run split Cypress E2E tests 🧪
# https://github.com/cypress-io/github-action
uses: cypress-io/github-action@v6
# using operating system process environment variables
env:
# should exclude these specs
SKIP_SPEC: 'cypress/e2e/spec-b.cy.js,cypress/e2e/spec-e.cy.js'
SPLIT: 2
SPLIT_INDEX: 0
DEBUG: 'cypress-split'

release:
if: github.ref == 'refs/heads/main'
needs:
[
test-skipped-specs,
test-unit,
test-empty,
test-split,
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,16 @@ Cannot parse as valid JSON
$ 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.
Expand Down
51 changes: 49 additions & 2 deletions src/parse-inputs.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,37 @@ function parseSplitInputs(env = {}, configEnv = {}) {
* @returns {string[]} list of spec filenames
*/
function getSpecsToSplit(env = {}, config) {
// potential list of specs to skip
let SKIP_SPEC =
env.SKIP_SPEC || config?.env?.skipSpec || config?.env?.SKIP_SPEC
const skipSpecs = []
if (typeof SKIP_SPEC === 'string' && SKIP_SPEC) {
const possiblePatterns = SKIP_SPEC.split(',')
.map((s) => s.trim())
.filter(Boolean)
.map((specFilename) => {
// make sure every spec filename is absolute
return path.resolve(specFilename)
})
// all resolved absolute spec filenames
possiblePatterns.forEach((pattern) => {
if (pattern.includes('*')) {
// the user specified the wildcard pattern
// resolve it using globby and searching the disk
const found = globby.sync(pattern)
skipSpecs.push(...found)
} else {
skipSpecs.push(pattern)
}
})
}
if (skipSpecs.length) {
debug('skipping %d specs', skipSpecs.length)
if (skipSpecs.length < 10) {
debug('skipping specs %o', skipSpecs)
}
}

// potentially a list of files to run / split
let SPEC = env.SPEC || config?.env?.spec || config?.env?.SPEC
if (typeof SPEC === 'string' && SPEC) {
Expand All @@ -85,11 +116,27 @@ function getSpecsToSplit(env = {}, config) {
specs.push(pattern)
}
})
return specs
// returned a filtered list
if (skipSpecs.length) {
debug(
'before skipping specs %d, filtering %d specs',
specs.length,
skipSpecs.length,
)
}
return specs.filter((spec) => !skipSpecs.includes(spec))
} else {
const returnAbsolute = true
const specs = getSpecs(config, undefined, returnAbsolute)
return specs
// returned a filtered list
if (skipSpecs.length) {
debug(
'before skipping specs %d, filtering %d specs',
specs.length,
skipSpecs.length,
)
}
return specs.filter((spec) => !skipSpecs.includes(spec))
}
}

Expand Down
16 changes: 16 additions & 0 deletions test/parse-inputs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ test('getSpecsToSplit spec pattern with wildcards', (t) => {
])
})

test('getSpecsToSplit with skip specs', (t) => {
const specs = getSpecsToSplit({
SPEC: 'cypress/e2e/spec-*.cy.js',
SKIP_SPEC: 'cypress/e2e/spec-b.cy.js',
})
// finds all specs matching the glob pattern
// but without "spec-b.cy.js"
const relativeSpecs = toRelative(specs)
t.deepEqual(relativeSpecs, [
'cypress/e2e/spec-a.cy.js',
'cypress/e2e/spec-c.cy.js',
'cypress/e2e/spec-d.cy.js',
'cypress/e2e/spec-e.cy.js',
])
})

test('getSpecsToSplit spec pattern with subfolder wildcards', (t) => {
const specs = getSpecsToSplit({
SPEC: 'cypress/**/spec-*.cy.js',
Expand Down