I use mocha -w --recursive cli to watch my test files changed.
But it will re-run all my tests, even I just modify a single test file.
I want something like just watch and re-run the __modified test file__ tracked by git?
Hi @mrdulin - very interesting! Mocha doesn't necessarily want to know about the GIT domain, because what about the Mercurial people and such.
Can I suggest you look into Husky or Lint Staged. Lint staged is probably what you're after, because it gives you a list of staged files.
@maraisr I am looking for a way that re-run the test file I modified , not all test files. Like Jest watch mode.
Hi @mrdulin, I had a similar issue and this is how I avoid re-running entire test suites.
Instead of watching all test files, you can specify files that you want to test/watch only.
For example,
// package.json
"tdd": "mocha ${TEST_FILES:-test/} --watch --recursive"
# terminal
TEST_FILES='test/a.spec.js test/b.spec.js' npm run tdd
This will only test files specified in TEST_FILES and watch the changes.
@junpos This seems like a manually work. My thought is If mocha know the test files modified which tracked by git . So mocha can re-run the modified test files.
@mrdulin I think git tracks all file changes not limited to test files. So Mocha doesn't know which files it should be watching at. Instead you can pass a list of filenames for Mocha with this simple bash script (I assume test files contain .spec.js)
# If your changes are not committed yet
mocha --watch $(git diff --name-only | grep .spec.js)
# If it's committed
mocha --watch $(git diff master... --name-only | grep .spec.js)
@junpos Yeah.git tracks all file changes. But Mocha should be care about the test files according to file extension or directory name. e.g: *.spec.js, *.test.js, /__tests__/.
Can you take a look about jest --watch cli option? I don't know do I explain clearly.
https://facebook.github.io/jest/docs/cli.html#watch
Watch files for changes and rerun tests related to changed files.
// package.json "tdd": "mocha ${TEST_FILES:-test/} --watch --recursive"# terminal TEST_FILES='test/a.spec.js test/b.spec.js' npm run tdd
This can be done without environment variables:
// package.json
"test": "mocha --watch --recursive"
# terminal
npm test test/a.spec.js test/b.spec.js
OR in test/mocha.opts
--watch --recursive
# terminal
mocha test/a.spec.js test/b.spec.js
My thought is If mocha know the test files modified which tracked by git .
Mocha doesn't know anything about Git, Mercurial, SVN etc.
To answer the question as generally as possible:
mocha.opts, are all "test files" -- they will be loaded with describe, it etc., which Mocha uses to run the tests.test directory; when a directory is specified Mocha will interpret it as referring to all .js files in that directory, or all .js files in the directory and all subdirectories if --recursive is also specified.--watch will rerun all the "test files" (see above) when any of the following are changed:.js extension--watch-extensionsMocha doesn't have any knowledge about which tests are testing which files; such a tool could presumably be built, but...
The built-in --watch feature has never been favored by Mocha's maintainers to begin with: the recommendation for more sophisticated watching behavior is to use an external watcher such as Chokidar (however, --watch has not been removed because we are aware of efficiency problems spawning an entirely new mocha process for each test run and consistency problems when making multiple runs through the programmatic API).
I am a bot that watches issues for inactivity.
This issue hasn't had any recent activity, and I'm labeling it stale. In 14 days, if there are no further comments or activity, I will close this issue.
Thanks for contributing to Mocha!
Hi, this script will allow you to execute only affected files. Please modify:
KNOWN ISSUE
This will not work if you are using imports by variables, such as const b = 'path', const a = require(b)
var watch = require('node-watch');
var execSync = require('child_process').execSync;
var dependencyTree = require('dependency-tree');
var glob = require('glob');
var changedFiles = [];
var timeout = null;
var trees = {};
const testFilter = '.test';
const fileFilter = /\.tsx?/;
function buildDependencyTree(filename) {
return dependencyTree({
filename,
isListForm: true,
directory: './src',
filter: path => path.indexOf('node_modules') === -1
});
}
function scan() {
glob('./src/**/*.test.ts?', {}, function(er, files) {
trees = {};
for (let file of files) {
trees[file.replace('./', '')] = buildDependencyTree(file);
}
});
}
scan();
watch('./', { recursive: true, filter: fileFilter }, function(evt, name) {
changedFiles.push(name);
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
try {
// build test list
let tests = [];
for (let file of changedFiles) {
if (file.indexOf(testFilter) >= 0) {
tests.push(file);
} else {
// find it in dependency tree
for (let f of Object.getOwnPropertyNames(trees)) {
if (trees[f].some(n => n.indexOf(file) >= 0)) {
tests.push(f);
}
}
}
}
changedFiles = [];
if (tests.length) {
let files = tests.join(',');
// CHANGE YOUR COMMAND
const command = `CI=true TS_NODE_FAST=true ./node_modules/.bin/mocha --exit '${files}' -P`;
console.log('\n-- Running --\n');
console.log(command);
execSync(command);
}
} catch (ex) {
} finally {
scan();
}
}, 100);
});
save as 'mocha-watch.js' in your root file and just add it to package.json as
{
"watch": "node mocha-watch"
}
@tomitrescak Hello Sir, I am using node js API project using javascript only not typescript. Then may I use this script and how? Please help, urgently needed.
Most helpful comment
Hi, this script will allow you to execute only affected files. Please modify:
KNOWN ISSUE
This will not work if you are using imports by variables, such as
const b = 'path', const a = require(b)save as 'mocha-watch.js' in your root file and just add it to package.json as