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

Does mocha watch the test files modified only? #2928

Closed
mrdulin opened this issue Jul 15, 2017 · 10 comments
Closed

Does mocha watch the test files modified only? #2928

mrdulin opened this issue Jul 15, 2017 · 10 comments
Labels
stale this has been inactive for a while... type: question support question

Comments

@mrdulin
Copy link

mrdulin commented Jul 15, 2017

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?

@maraisr
Copy link
Contributor

maraisr commented Jul 17, 2017

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.

@mrdulin
Copy link
Author

mrdulin commented Jul 18, 2017

@maraisr I am looking for a way that re-run the test file I modified , not all test files. Like Jest watch mode.

@junpos
Copy link

junpos commented Jul 28, 2017

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.

@mrdulin
Copy link
Author

mrdulin commented Jul 28, 2017

@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.

@junpos
Copy link

junpos commented Jul 31, 2017

@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)

@mrdulin
Copy link
Author

mrdulin commented Aug 1, 2017

@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.

@ScottFreeCode
Copy link
Contributor

ScottFreeCode commented Aug 1, 2017

// 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:

  • Any files passed to Mocha, whether by NPM script or by the CLI command, and any files specified in mocha.opts, are all "test files" -- they will be loaded with describe, it etc., which Mocha uses to run the tests.
    • The default file is the 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:
    • any files in the project, whether test files or not, with the .js extension
    • any files in the project, whether test files or not, with extensions specified in --watch-extensions

Mocha 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).

@ScottFreeCode ScottFreeCode added the type: question support question label Sep 4, 2017
@stale
Copy link

stale bot commented Jan 2, 2018

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!

@stale stale bot added the stale this has been inactive for a while... label Jan 2, 2018
@stale stale bot closed this as completed Jan 16, 2018
@tomitrescak
Copy link

tomitrescak commented Mar 8, 2018

Hi, this script will allow you to execute only affected files. Please modify:

  1. your mocha execution pattern to fit your needs
  2. your file matcher
  3. your test matcher

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"
}

@sudhir512kj
Copy link

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale this has been inactive for a while... type: question support question
Projects
None yet
Development

No branches or pull requests

6 participants