Improve server test scripts (#6567)

* clean up server test commands

this mostly restores the pre-yarn behavior:
- passing a file path to a test command runs that file, not all tests
- there is only one test-watch
- there is a "test" command which accepts a pathx

* allow run.js to specify multiple specfiles

* simplify e2e test setup by using globbing

* fix e2e test that has been broken for eternity

* still let users use `test-e2e --spec` syntax

* update server README
This commit is contained in:
Zach Bloomquist
2020-02-26 15:53:43 -05:00
committed by GitHub
parent f77ec01c18
commit 17c9ded463
10 changed files with 83 additions and 202 deletions

View File

@@ -24,12 +24,12 @@
"command": "yarn test-watch [file]"
},
{
"name": "packages/server test-e2e",
"name": "packages/server test",
"focus": true,
"onlySingle": true,
"execute": false,
"cwd": "[cwd]/packages/server",
"command": "yarn test-e2e --spec [fileBasename]"
"command": "yarn test [file]"
},
{
"name": "packages/runner watch",

View File

@@ -97,7 +97,7 @@ commands:
- attach_workspace:
at: ~/
- run:
command: yarn lerna exec --scope @packages/server "yarn test-e2e --chunk << parameters.chunk >> --browser << parameters.browser >>"
command: yarn lerna exec --scope @packages/server "yarn test ./test/e2e/<< parameters.chunk >>*spec* --browser << parameters.browser >>"
- verify-mocha-results
- store_test_results:
path: /tmp/cypress

View File

@@ -17,11 +17,11 @@ The [driver](../driver) and the server are the two most complex packages of Cypr
## Developing
To run Cypress:
To run the Cypress server:
```bash
## boots the entire Cypress application
yarn lerna run start --scope @packages/server --stream
yarn start
```
Since the server controls nearly every aspect of Cypress, after making changes you'll need to manually restart Cypress.
@@ -36,19 +36,52 @@ Note: you should not ever need to build the .js files manually. `@packages/ts` p
yarn lerna run build-prod --scope @packages/server --stream
```
## Testing
* `yarn test-unit` executes unit tests in [`test/unit`](./test/unit)
* `yarn test-integration` executes integration tests in [`test/integration`](./test/integration)
* `yarn test-performance` executes performance tests in [`test/performance`](./test/performance)
* `yarn test-e2e` executes the large (slow) end to end tests in [`test/e2e`](./test/e2e)
* `yarn lerna run test-unit --scope @packages/server --stream` executes unit tests in [`test/unit`](./test/unit)
* `yarn lerna run test-integration --scope @packages/server --stream` executes integration tests in [`test/integration`](./test/integration)
* `yarn lerna run test-performance --scope @packages/server --stream` executes performance tests in [`test/performance`](./test/performance)
* `yarn lerna run test-e2e --scope @packages/server --stream` executes the large (slow) end to end tests in [`test/e2e`](./test/e2e)
Each of these tasks can run in "watch" mode by appending `-watch` to the task:
You can also use the `test-watch` command to rerun a test file whenever there is a change:
```bash
yarn lerna run test-unit-watch --scope @packages/server --stream
yarn test-watch /test/path/to/spec.js
```
When running e2e tests, some test projects output verbose logs. To see them run the test with `DEBUG=cypress:e2e` environment variable.
To update snapshots, see `snap-shot-it` instructions: https://github.com/bahmutov/snap-shot-it#advanced-use
### Running individual unit tests
```bashtest-kitchensink
yarn test <path/to/test>
yarn test test/unit/api_spec.coffee
## or
yarn test-unit api_spec ## shorthand, uses globbing to find spec
```
### Running individual integration tests
```bash
yarn test <path/to/test>
yarn test test/integration/cli_spec.coffee
## or
yarn test-integration cli_spec ## shorthand, uses globbing to find spec
```
### Running individual e2e tests
```bash
yarn test <path/to/test>
yarn test test/e2e/1_async_timeouts_spec.coffee
## or
yarn test-e2e 1_async ## shorthand, uses globbing to find spec
```
### Updating snaphots
Prepend `SNAPSHOT_UPDATE=1` to any test command. See [`snap-shot-it` instructions](https://github.com/bahmutov/snap-shot-it#advanced-use) for more info.
```bash
SNAPSHOT_UPDATE=1 yarn test test/unit/api_spec.coffee
SNAPSHOT_UPDATE=1 yarn test test/integration/cli_spec.coffee
SNAPSHOT_UPDATE=1 yarn test-e2e 1_async
```

View File

@@ -1,4 +1,4 @@
exports['e2e issue 2891 passes 1'] = `
exports['e2e issue 1669 passes 1'] = `
====================================================================================================

View File

@@ -11,17 +11,14 @@
"lint-coffee": "coffeelint test/*.coffee test/unit/*.coffee test/integration/*.coffee",
"repl": "node repl.js",
"start": "node ../../scripts/cypress open --dev --global",
"test": "node ./test/scripts/run.js",
"test-cov": "cross-env NODE_COVERAGE=true NODE_ENV=test CYPRESS_ENV=test BLUEBIRD_DEBUG=1 xvfb-maybe istanbul cover node_modules/.bin/_mocha -- --opts ./test/support/mocha.opts",
"test-cov-process": "cross-env NODE_COVERAGE=true NODE_ENV=test CYPRESS_ENV=test BLUEBIRD_DEBUG=1 istanbul cover --include-pid",
"test-debug": "yarn test-unit --inspect-brk=5566",
"test-e2e": "node ./test/scripts/e2e.js",
"test-e2e-chrome": "node ./test/scripts/run.js test/e2e chrome",
"test-integration": "node ./test/scripts/run.js test/integration",
"test-integration-watch": "./test/support/watch test-integration",
"test-performance": "node ./test/scripts/run.js test/performance",
"test-unit": "node ./test/scripts/run.js test/unit",
"test-unit-watch": "./test/support/watch test/unit",
"test-watch": "./test/support/watch test-unit"
"test-e2e": "node ./test/scripts/run.js --glob-in-dir=test/e2e",
"test-integration": "node ./test/scripts/run.js --glob-in-dir=test/integration",
"test-performance": "node ./test/scripts/run.js --glob-in-dir=test/performance",
"test-unit": "node ./test/scripts/run.js --glob-in-dir=test/unit",
"test-watch": "./test/support/watch test"
},
"dependencies": {
"@benmalka/foxdriver": "0.2.3",

View File

@@ -1,10 +1,10 @@
e2e = require("../support/helpers/e2e")
Fixtures = require("../support/helpers/fixtures")
describe "e2e issue 2891", ->
describe "e2e issue 1669", ->
e2e.setup()
## https://github.com/cypress-io/cypress/issues/2891
## https://github.com/cypress-io/cypress/issues/1669
it "passes", ->
e2e.exec(@, {

View File

@@ -1,85 +0,0 @@
/* eslint-disable no-console */
require('@packages/coffee/register')
const _ = require('lodash')
const cp = require('child_process')
const path = require('path')
const minimist = require('minimist')
const Promise = require('bluebird')
const terminalBanner = require('terminal-banner').terminalBanner
const glob = require('../../lib/util/glob')
const humanTime = require('../../lib/util/human_time')
const options = minimist(process.argv.slice(2))
if (options.browser) {
process.env.BROWSER = options.browser
}
const started = new Date()
let numFailed = 0
function isLoadBalanced (options) {
return _.isNumber(options.chunk)
}
function spawn (cmd, args, opts) {
return new Promise((resolve, reject) => {
cp.spawn(cmd, args, opts)
.on('exit', resolve)
.on('error', reject)
})
}
glob('test/e2e/**/*')
.then((specs = []) => {
if (options.spec) {
return _.filter(specs, (spec) => {
return _.some(options.spec.split(','), (specPart) => {
return spec.includes(specPart)
})
})
}
if (isLoadBalanced(options)) {
return _.filter(specs, (spec) => {
return path.basename(spec).startsWith(options.chunk)
})
}
return specs
})
.tap(console.log)
.each((spec = []) => {
terminalBanner(`Running spec ${spec}`, '*')
const args = [
'./test/scripts/run.js',
spec,
]
if (options['inspect-brk']) {
args.push('--inspect-brk')
}
return spawn('node', args, { stdio: 'inherit' })
.then((code) => {
console.log(`${spec} exited with code`, code)
numFailed += code
})
.catch((err) => {
console.log(err)
throw err
})
})
.then(() => {
const duration = new Date() - started
console.log('Total duration:', humanTime.long(duration))
console.log('Exiting with final code:', numFailed)
process.exit(numFailed)
})

View File

@@ -1,80 +0,0 @@
/* eslint-disable no-console */
require('@packages/coffee/register')
const _ = require('lodash')
const path = require('path')
const Promise = require('bluebird')
const minimist = require('minimist')
const fs = require('../../lib/util/fs')
const glob = require('../../lib/util/glob')
const options = minimist(process.argv.slice(2))
const { size, reset, snapshots } = options
const removeChunkPrefixes = () => {
const forwardSlashNumUnderscoreRe = /(\/\d_)/
const renameFiles = (pattern) => {
return glob(pattern)
.map((spec) => {
return fs.renameAsync(spec, spec.replace(forwardSlashNumUnderscoreRe, '/'))
})
}
return Promise.join(
renameFiles('test/e2e/**/*'),
renameFiles('__snapshots__/**/*'),
)
}
const renameSnapshotsToMatchSpecs = () => {
glob('test/e2e/**/*')
.map((spec) => {
spec += '.js'
const specName = path.basename(spec)
const pathToSnapshot = path.resolve(
__dirname, '..', '..', '__snapshots__', specName.slice(2),
)
const pathToRenamedSnapshot = path.join(
path.dirname(pathToSnapshot),
specName,
)
return fs.renameAsync(pathToSnapshot, pathToRenamedSnapshot)
})
.catchReturn({ code: 'ENOENT' }, null)
}
if (reset) {
return removeChunkPrefixes()
}
if (snapshots) {
return renameSnapshotsToMatchSpecs()
}
glob('test/e2e/**/*')
.then((specs) => {
if (!size) {
console.error('must include --size for calculating chunk size')
}
return _.chunk(specs, size)
})
.map((chunks, index) => {
index += 1
return Promise
.map(chunks, (spec) => {
const folder = path.dirname(spec)
const specName = path.basename(spec)
const renamedSpec = `${index}_${specName}`
return fs.renameAsync(spec, path.join(folder, renamedSpec))
})
})

View File

@@ -4,14 +4,28 @@ const _ = require('lodash')
const chalk = require('chalk')
const minimist = require('minimist')
const execa = require('execa')
const path = require('path')
const os = require('os')
const options = minimist(process.argv.slice(2))
let run = options._[0]
let run = options._
if (run && run.includes('--inspect-brk')) {
run = options._[1]
if (options['spec']) {
console.error('NOTE: It is no longer necessary to pass `--spec` to server test commands. Try passing the path directly instead.')
run = [options.spec]
}
if (run[0] && run[0].includes('--inspect-brk')) {
run = run.slice(1)
}
if (options['glob-in-dir']) {
if (run[0]) {
run = [path.join(options['glob-in-dir'], '**', `*${run[0]}*`)]
} else {
run = [options['glob-in-dir']]
}
}
function exitErr (msg) {
@@ -28,19 +42,19 @@ const isGteNode12 = () => {
return Number(process.versions.node.split('.')[0]) >= 12
}
if (!run) {
if (!run || !run.length) {
return exitErr(`
Error: A path to a spec file must be specified!
It should look something like this:
$ npm test ./test/unit/api_spec.coffee
$ yarn test ./test/unit/api_spec.coffee
If you want to run all a specific group of tests:
$ npm run test-unit
$ npm run test-integration
$ npm run test-e2e
$ yarn test-unit
$ yarn test-integration
$ yarn test-e2e
`)
}
@@ -51,7 +65,7 @@ const commandAndArguments = {
if (isWindows()) {
commandAndArguments.command = 'mocha'
commandAndArguments.args = [run]
commandAndArguments.args = run.slice()
} else {
commandAndArguments.command = 'xvfb-maybe'
commandAndArguments.args = [
@@ -79,8 +93,9 @@ if (isGteNode12()) {
if (!isWindows()) {
commandAndArguments.args.push(
'node_modules/.bin/_mocha',
run,
)
commandAndArguments.args = commandAndArguments.args.concat(run)
}
if (options.fgrep) {
@@ -132,6 +147,7 @@ if (options.browser) {
const cmd = `${commandAndArguments.command} ${
commandAndArguments.args.join(' ')}`
console.log('specfiles:', run)
console.log('test command:')
console.log(cmd)

View File

@@ -5,6 +5,6 @@ ARGS="$2"
npm run --silent $CMD $ARGS & \
chokidar 'test/**/*' 'lib/**/*' \
-c "npm run --silent $CMD $ARGS" \
-c "yarn --silent $CMD $ARGS" \
--polling \
--poll-interval=250