Skip to content

Commit

Permalink
Close #592 PR: Add match CLI option to run only matching tests. Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
kasperlewau authored and sindresorhus committed Mar 5, 2016
1 parent fc544ed commit c928cb5
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 5 deletions.
10 changes: 7 additions & 3 deletions cli.js
Expand Up @@ -49,6 +49,7 @@ var cli = meow([
' --tap, -t Generate TAP output',
' --verbose, -v Enable verbose output',
' --no-cache Disable the transpiler cache',
' --match, -m Only run tests with matching title (Can be repeated)',
// Leave --watch and --sources undocumented until they're stable enough
// ' --watch, -w Re-run tests when tests and source files change',
// ' --source Pattern to match source files so tests can be re-run (Can be repeated)',
Expand All @@ -67,7 +68,8 @@ var cli = meow([
string: [
'_',
'require',
'source'
'source',
'match'
],
boolean: [
'fail-fast',
Expand All @@ -82,7 +84,8 @@ var cli = meow([
v: 'verbose',
r: 'require',
s: 'serial',
w: 'watch'
w: 'watch',
m: 'match'
}
});

Expand All @@ -98,7 +101,8 @@ var api = new Api({
serial: cli.flags.serial,
require: arrify(cli.flags.require),
cacheEnabled: cli.flags.cache !== false,
explicitTitles: cli.flags.watch
explicitTitles: cli.flags.watch,
match: arrify(cli.flags.match)
});

var reporter;
Expand Down
3 changes: 2 additions & 1 deletion index.js
Expand Up @@ -13,7 +13,8 @@ require('./lib/test-worker').avaRequired = true;
var opts = globals.options;
var runner = new Runner({
serial: opts.serial,
bail: opts.failFast
bail: opts.failFast,
match: opts.match
});

// check if the test is being run without AVA cli
Expand Down
6 changes: 6 additions & 0 deletions lib/runner.js
Expand Up @@ -3,6 +3,7 @@ var EventEmitter = require('events').EventEmitter;
var util = require('util');
var Promise = require('bluebird');
var optionChain = require('option-chain');
var matcher = require('matcher');
var TestCollection = require('./test-collection');

function noop() {}
Expand Down Expand Up @@ -42,6 +43,7 @@ function Runner(options) {
this.tests = new TestCollection();
this._bail = options.bail;
this._serial = options.serial;
this._match = options.match;

this._addTestResult = this._addTestResult.bind(this);
}
Expand Down Expand Up @@ -69,6 +71,10 @@ optionChain(chainableMethods, function (opts, title, fn) {
opts.serial = true;
}

if (opts.type === 'test' && title !== null && this._match && this._match.length > 0) {
opts.exclusive = matcher([title], this._match).length > 0;
}

this.tests.add({
metadata: opts,
fn: fn,
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -106,6 +106,7 @@
"is-promise": "^2.1.0",
"last-line-stream": "^1.0.0",
"loud-rejection": "^1.2.0",
"matcher": "^0.1.1",
"max-timeout": "^1.0.0",
"md5-hex": "^1.2.0",
"meow": "^3.7.0",
Expand Down
48 changes: 48 additions & 0 deletions readme.md
Expand Up @@ -115,6 +115,7 @@ $ ava --help
--tap, -t Generate TAP output
--verbose, -v Enable verbose output
--no-cache Disable the transpiler cache
--match, -m Only run tests with matching title (Can be repeated)',
Examples
ava
Expand Down Expand Up @@ -145,6 +146,10 @@ All of the CLI options can be configured in the `ava` section of your `package.j
"my-test-folder/*.js",
"!**/not-this-file.js"
],
"match": [
"*oo",
"!foo"
],
"failFast": true,
"tap": true,
"require": [
Expand Down Expand Up @@ -246,6 +251,49 @@ test.only('will be run', t => {
});
```

### Matched-tests

The `--match` flag allows you to run a subset of the tests in your suite that have a matching title. This is achieved with simple wildcard patterns. For more information, check out [matcher](https://github.com/sindresorhus/matcher).

```
# match titles ending with 'foo'
$ ava --match='*foo'
# match titles starting with 'foo'
$ ava --match='foo*'
# match titles containing 'foo'
$ ava --match='*foo*'
# match titles not containing 'foo'
$ ava --match='!*foo*'
# match titles starting with 'foo' and ending with 'bar'
$ ava --match='foo*bar'
# match titles starting with 'foo' or ending with 'bar'
$ ava --match='foo*' --match='*bar'
```

```js
// $ ava --match='*oo'

test('foo will run', t => {
t.pass();
});

test.only('moo will also run', t => {
t.pass();
});

// won't run!
test(function () {
t.fail();
});
```

Note that a match pattern takes precedence over `.only`, and *any tests without an explicit title will* **not run** *if a match pattern is supplied.*

### Skip-tests

Skip-tests are shown in the output as skipped but never run. Skip-tests require a function.
Expand Down
9 changes: 8 additions & 1 deletion test/cli.js
Expand Up @@ -112,7 +112,7 @@ test('pkg-conf: pkg-overrides', function (t) {
});

test('pkg-conf: cli takes precedence', function (t) {
execCli(['--no-serial', '--cache', '--no-fail-fast', '--require=./required.js', 'c.js'], {dirname: 'fixture/pkg-conf/precedence'}, function (err) {
execCli(['--match=foo*', '--no-serial', '--cache', '--no-fail-fast', '--require=./required.js', 'c.js'], {dirname: 'fixture/pkg-conf/precedence'}, function (err) {
t.ifError(err);
t.end();
});
Expand Down Expand Up @@ -156,6 +156,13 @@ test('watcher works', function (t) {
});
});

test('--match works', function (t) {
execCli(['-m=foo', '-m=bar', '-m=!baz', '-m=t* a* f*', '-m=!t* a* n* f*', 'fixture/matcher-skip.js'], function (err) {
t.ifError(err);
t.end();
});
});

test('handles NODE_PATH', function (t) {
var nodePaths = 'fixture/node-paths/modules' + path.delimiter + 'fixture/node-paths/deep/nested';

Expand Down
21 changes: 21 additions & 0 deletions test/fixture/matcher-skip.js
@@ -0,0 +1,21 @@
import test from '../../';

test('foo', t => {
t.pass();
});

test('bar', t => {
t.pass();
});

test('baz', t => {
t.fail();
});

test('tests are fun', t => {
t.pass();
});

test('tests are not fun', t => {
t.fail();
});
1 change: 1 addition & 0 deletions test/fixture/pkg-conf/precedence/c.js
Expand Up @@ -7,6 +7,7 @@ test(t => {
t.is(opts.failFast, false);
t.is(opts.serial, false);
t.is(opts.cacheEnabled, true);
t.same(opts.match, ['foo*']);
t.same(opts.require, [
path.join(__dirname, "required.js")
]);
Expand Down
1 change: 1 addition & 0 deletions test/fixture/pkg-conf/precedence/package.json
Expand Up @@ -6,6 +6,7 @@
"serial": true,
"failFast": true,
"cache": false,
"match": ["*"],
"require": "./default-required.js"
}
}
79 changes: 79 additions & 0 deletions test/runner.js
Expand Up @@ -378,3 +378,82 @@ test('options.bail + serial - tests will never happen (async)', function (t) {
}, 250);
});
});

test('options.match will not run tests with non-matching titles', function (t) {
t.plan(5);

var runner = new Runner({
match: ['*oo', '!foo']
});

runner.test('mhm. grass tasty. moo', function () {
t.pass();
});

runner.test('juggaloo', function () {
t.pass();
});

runner.test('foo', function () {
t.fail();
});

runner.test(function () {
t.fail();
});

runner.run({}).then(function () {
t.is(runner.stats.skipCount, 0);
t.is(runner.stats.passCount, 2);
t.is(runner.stats.testCount, 2);
t.end();
});
});

test('options.match hold no effect on hooks with titles', function (t) {
t.plan(4);

var runner = new Runner({
match: ['!before*']
});

var actual;

runner.before('before hook with title', function () {
actual = 'foo';
});

runner.test('after', function () {
t.is(actual, 'foo');
});

runner.run({}).then(function () {
t.is(runner.stats.skipCount, 0);
t.is(runner.stats.passCount, 1);
t.is(runner.stats.testCount, 1);
t.end();
});
});

test('options.match overrides .only', function (t) {
t.plan(5);

var runner = new Runner({
match: ['*oo']
});

runner.test('moo', function () {
t.pass();
});

runner.test.only('boo', function () {
t.pass();
});

runner.run({}).then(function () {
t.is(runner.stats.skipCount, 0);
t.is(runner.stats.passCount, 2);
t.is(runner.stats.testCount, 2);
t.end();
});
});

0 comments on commit c928cb5

Please sign in to comment.