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

📦 NEW: Support run test with node:test #177

Merged
merged 5 commits into from Jun 4, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 7 additions & 1 deletion .eslintrc
@@ -1,3 +1,9 @@
{
"extends": "eslint-config-egg"
"extends": "eslint-config-egg",
"rules": {
/**
* @see http://eslint.org/docs/rules/strict
*/
"strict": [ "off" ]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}
76 changes: 63 additions & 13 deletions README.md
Expand Up @@ -17,15 +17,14 @@
[download-image]: https://img.shields.io/npm/dm/egg-bin.svg?style=flat-square
[download-url]: https://npmjs.org/package/egg-bin


egg developer tool, extends [common-bin].

---

## Install

```bash
$ npm i egg-bin --save-dev
npm i egg-bin --save-dev
```

## Usage
Expand Down Expand Up @@ -58,7 +57,7 @@ All the commands support these specific v8 options:
- `--es_staging`

```bash
$ egg-bin [command] --debug --es_staging
egg-bin [command] --debug --es_staging
```

if `process.env.NODE_DEBUG_OPTION` is provided (WebStorm etc), will use it as debug options.
Expand All @@ -68,7 +67,7 @@ if `process.env.NODE_DEBUG_OPTION` is provided (WebStorm etc), will use it as de
Start dev cluster on `local` env, it will start a master, an agent and a worker.

```bash
$ egg-bin dev
egg-bin dev
```

##### options
Expand All @@ -91,23 +90,22 @@ automatically detect the protocol, use the new `inspector` when the targeted run
if running without `VSCode` or `WebStorm`, we will use [inspector-proxy](https://github.com/whxaxes/inspector-proxy) to proxy worker debug, so you don't need to worry about reload.

```bash
$ egg-bin debug --debug-port=9229 --proxy=9999
egg-bin debug --debug-port=9229 --proxy=9999
```

##### options

- all `egg-bin dev` options is accepted.
- `--proxy=9999` worker debug proxy port.


### test

Using [mocha] to run test.

[power-assert] is the default `assert` library, and [intelli-espower-loader] will be auto required.

```bash
$ egg-bin test [files] [options]
egg-bin test [files] [options]
```

- `files` is optional, default to `test/**/*.test.js`
Expand All @@ -128,14 +126,14 @@ test
You can pass any mocha argv.

- `--require` require the given module
- `--grep` only run tests matching <pattern>
- `--grep` only run tests matching `<pattern>`
- `--timeout` milliseconds, default to 60000
- `--full-trace` display the full stack trace, default to false.
- `--typescript` / `--ts` enable typescript support, default to `false`.
- `--changed` / `-c` only test changed test files(test files means files that match `${pwd}/test/**/*.test.(js|ts)`)
- `--dry-run` / `-d` whether dry-run the test command, just show the command
- `--dry-run` / `-d` whether dry-run the test command, just show the command
- `--espower` / `-e` whether auto require intelli-espower-loader(js) or espower-typescript(ts) for power-assert, default to `true`.
- see more at https://mochajs.org/#usage
- see more at <https://mochajs.org/#usage>

#### environment

Expand All @@ -159,6 +157,55 @@ The test timeout can set by `TEST_TIMEOUT` env, default is `60000` ms.
TEST_TIMEOUT=2000 egg-bin test
```

### node-test

Using [node:test] to run test.

[power-assert] is the default `assert` library, and [intelli-espower-loader] will be auto required.

```bash
egg-bin node-test [files] [options]
```

- `files` is optional, default to `test/**/*.test.js`
- `test/fixtures`, `test/node_modules` is always exclude.

#### auto require `test/.setup.js`

If `test/.setup.js` file exists, it will be auto require as the first test file.

```js
test
├── .setup.js
└── foo.test.js
```

#### node:test options

- `--test-only` configures the test runner to only execute top level tests that have the only option set

#### environment

Environment is also support, will use it if options not provide.

You can set `TESTS` env to set the tests directory, it support [glob] grammar.

```bash
TESTS=test/a.test.js egg-bin node-test
```

And the reporter can set by the `TEST_REPORTER` env, default is `tap`.

```bash
TEST_REPORTER=doc egg-bin node-test
```

The test timeout can set by `TEST_TIMEOUT` env, default is `60000` ms.

```bash
TEST_TIMEOUT=2000 egg-bin node-test
```

### cov

Using [c8] to run code coverage, it support all test params above.
Expand All @@ -173,8 +220,10 @@ You can pass any mocha argv.
- `--prerequire` prerequire files for coverage instrument, you can use this options if load files slowly when call `mm.app` or `mm.cluster`
- `--typescript` / `--ts` enable typescript support, default to `false`, if true, will auto add `.ts` extension and ignore `typings` and `d.ts`.
- `--c8` c8 instruments passthrough. you can use this to overwrite egg-bin's default c8 instruments and add additional ones.
>
> - egg-bin have some default instruments passed to c8 like `-r` and `--temp-directory`
> - `egg-bin cov --c8="-r teamcity -r text" --c8-report=true`
>
- `--c8-report` use c8 to report coverage, c8 uses native V8 coverage, make sure you're running Node.js >= 10.12.0, default to `false`.

- also support all test params above.
Expand All @@ -184,23 +233,23 @@ You can pass any mocha argv.
You can set `COV_EXCLUDES` env to add dir ignore coverage.

```bash
$ COV_EXCLUDES="app/plugins/c*,app/autocreate/**" egg-bin cov
COV_EXCLUDES="app/plugins/c*,app/autocreate/**" egg-bin cov
```

### pkgfiles

Generate `pkg.files` automatically before npm publish, see [ypkgfiles] for detail

```bash
$ egg-bin pkgfiles
egg-bin pkgfiles
```

### autod

Generate `pkg.dependencies` and `pkg.devDependencies` automatically, see [autod] for detail

```bash
$ egg-bin autod
egg-bin autod
```

## Custom egg-bin for your team
Expand Down Expand Up @@ -293,6 +342,7 @@ This project follows the git-contributor [spec](https://github.com/xudafeng/git-
<!-- GITCONTRIBUTOR_END -->

[mocha]: https://mochajs.org
[node:test]: https://nodejs.org/api/test.html
[glob]: https://github.com/isaacs/node-glob
[nsp]: https://npmjs.com/nsp
[iron-node]: https://github.com/s-a/iron-node
Expand Down
144 changes: 144 additions & 0 deletions lib/cmd/node-test.js
@@ -0,0 +1,144 @@
'use strict';

const debug = require('debug')('egg-bin');
const fs = require('fs');
const path = require('path');
const globby = require('globby');
const Command = require('../command');
const { getChangedTestFiles } = require('../utils');

class NodeTestCommand extends Command {
constructor(rawArgv) {
super(rawArgv);
this.usage = 'Usage: egg-bin node-test [files] [options]';
this.options = {
require: {
description: 'require the given module',
alias: 'r',
type: 'array',
},
grep: {
description: 'only run tests matching <pattern>',
alias: 'g',
type: 'array',
},
timeout: {
description: 'set test-case timeout in milliseconds',
alias: 't',
type: 'number',
},
changed: {
description: 'only test with changed files and match ${cwd}/test/**/*.test.(js|ts)',
alias: 'c',
},
};
}

get description() {
return 'Run test with node:test';
}

async run(context) {
const opt = {
env: Object.assign({
NODE_ENV: 'test',
}, context.env),
execArgv: context.execArgv,
};
const testArgs = await this.formatTestArgs(context);
if (!testArgs) return;

if (parseInt(process.version.split('.')[0].substring(1)) < 18) {
// using user land test module
// https://github.com/nodejs/node-core-test
const nodeTestBin = require.resolve('test/bin/node--test');
debug('run test: %s %s', nodeTestBin, testArgs.join(' '));
await this.helper.forkNode(nodeTestBin, testArgs, opt);
return;
}
testArgs.unshift('--test');
debug('run test: %s %s', process.execPath, testArgs.join(' '));
await this.helper.spawn(process.execPath, testArgs, opt);
}

/**
* format test args then change it to array style
* @param {Object} context - { cwd, argv, ...}
* @param context.argv
* @return {Array} [ '--require=xxx', 'xx.test.js' ]
* @protected
*/
async formatTestArgs({ argv }) {
const testArgv = Object.assign({}, argv);

/* istanbul ignore next */
// testArgv.timeout = testArgv.timeout || process.env.TEST_TIMEOUT || 60000;
// testArgv.reporter = testArgv.reporter || process.env.TEST_REPORTER;

// collect require
let requireArr = testArgv.require || testArgv.r || [];
/* istanbul ignore next */
if (!Array.isArray(requireArr)) requireArr = [ requireArr ];

testArgv.require = requireArr;

let pattern;
// changed
if (testArgv.changed) {
pattern = await this._getChangedTestFiles();
if (!pattern.length) {
console.log('No changed test files');
return;
}
}

if (!pattern) {
// specific test files
pattern = testArgv._.slice();
}
if (!pattern.length && process.env.TESTS) {
pattern = process.env.TESTS.split(',');
}

// collect test files
if (!pattern.length) {
pattern = [ `test/**/*.test.${testArgv.typescript ? 'ts' : 'js'}` ];
}
pattern = pattern.concat([ '!test/fixtures', '!test/node_modules' ]);

// expand glob and skip node_modules and fixtures
const files = globby.sync(pattern);
files.sort();

if (files.length === 0) {
console.log(`No test files found with ${pattern}`);
return;
}

// auto add setup file as the first test file
const setupFile = path.join(process.cwd(), `test/.setup.${testArgv.typescript ? 'ts' : 'js'}`);
if (fs.existsSync(setupFile)) {
files.unshift(setupFile);
}
testArgv._ = files;

// remove alias
testArgv.$0 = undefined;
testArgv.r = undefined;
testArgv.t = undefined;
testArgv.g = undefined;
testArgv.e = undefined;
testArgv['dry-run'] = undefined;
testArgv.dryRun = undefined;
// not support tscompiler for now
testArgv.tscompiler = undefined;

return this.helper.unparseArgv(testArgv);
}

async _getChangedTestFiles() {
return await getChangedTestFiles(process.cwd());
}
}

module.exports = NodeTestCommand;
14 changes: 2 additions & 12 deletions lib/cmd/test.js
Expand Up @@ -4,8 +4,8 @@ const debug = require('debug')('egg-bin');
const fs = require('fs');
const path = require('path');
const globby = require('globby');
const changed = require('jest-changed-files');
const Command = require('../command');
const { getChangedTestFiles } = require('../utils');

class TestCommand extends Command {
constructor(rawArgv) {
Expand Down Expand Up @@ -176,17 +176,7 @@ class TestCommand extends Command {
}

async _getChangedTestFiles() {
const cwd = process.cwd();
const res = await changed.getChangedFilesForRoots([ cwd ]);
const changedFiles = res.changedFiles;
const files = [];
for (const file of changedFiles) {
// only find ${cwd}/test/**/*.test.(js|ts)
if (file.startsWith(path.join(cwd, 'test')) && file.match(/\.test\.(js|ts)$/)) {
files.push(file);
}
}
return files;
return await getChangedTestFiles(process.cwd());
}
}

Expand Down
17 changes: 17 additions & 0 deletions lib/utils.js
@@ -0,0 +1,17 @@
const path = require('path');
const changed = require('jest-changed-files');

module.exports = {
async getChangedTestFiles(dir) {
const res = await changed.getChangedFilesForRoots([ dir ]);
const changedFiles = res.changedFiles;
const files = [];
for (const file of changedFiles) {
// only find ${dir}/test/**/*.test.(js|ts)
if (file.startsWith(path.join(dir, 'test')) && file.match(/\.test\.(js|ts)$/)) {
files.push(file);
}
}
return files;
},
};
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -34,6 +34,7 @@
"power-assert": "^1.6.1",
"semver": "^7.3.7",
"source-map-support": "^0.5.21",
"test": "^3.0.0",
"test-exclude": "^6.0.0",
"ts-node": "^10.8.0",
"ypkgfiles": "^1.6.0"
Expand Down