35

In my npm package, I would like to emulate the pattern Meteor follows: a source file (named client.js) has a test file (named client.tests.js) live in a src/ folder. Tests run with the npm test command.

I'm following the usage docs to the 't'. I do not want to use a find in my package test command.

  1. I understand that mocha can recursively execute tests:

    mocha --recursive

  2. I understand that mocha can execute tests in a specific subfolder using the --recursive flag:

    mocha src --recursive

  3. I also understand that I can specify a glob to filter files by passing *.tests.js:

    mocha *.tests.js

But, I want all three. I want mocha to test only files ending in tests.js in the src folder, recursively checking subdirectories.

mocha --recursive *.tests.js

// See the files?
$ > ll ./src/app/
total 168
-rw-r--r--  ... client.js
-rw-r--r--  ... client.tests.js

// Option A
$ > mocha --recursive *.tests.js
Warning: Could not find any test files matching pattern: *.tests.js
No test files found

// Option B
$ > mocha *.tests.js --recursive
Warning: Could not find any test files matching pattern: *.tests.js
No test files found.

// Option C
$ > mocha --recursive src/app/*.tests.js
3 passing (130ms)
3 failing

So...

  1. Why is mocha not picking up the *.tests.js files in the subfolders?
  2. Why DOES it work if I specify the full path to the file?
  3. How do I make it work as desired?
4Z4T4R
  • 2,340
  • 2
  • 26
  • 45
  • 1
    did you tried with this glob: `src/app/**/*.tests.js`? – pablogq Mar 24 '17 at 17:28
  • Indeed I did not. For my own reference, where can I find this glob syntax documented? I turned a few stones before polling SO. Curious. Thx. – 4Z4T4R Mar 24 '17 at 22:29
  • 1
    you can find more info about the glob syntax in the README of the [glob](https://github.com/isaacs/node-glob) package repository. That's the package used by mocha. – pablogq Mar 24 '17 at 23:14
  • Oh. My. GLOB. _LoLz_ – 4Z4T4R Mar 27 '17 at 18:32

2 Answers2

82

The --recursive flag is meant to operate on directories. If you were to pass a glob that matches directories, then these directories would be examined recursively but if you pass a glob that matches files, like you are doing, then --recursive is ineffective. I would suggest not using --recursive with a glob because globs already have the capability to look recursively in subdirectories. You could do:

mocha 'src/app/**/*.tests.js'

This would match all files that match *.tests.js recursively in src/app. Note how I'm using single quotes around the pattern. This is to quote the pattern so that it is passed as-is to Mocha's globbing code. Otherwise, your shell might interpret it. Some shells, depending on options, will translate ** into * and you won't get the results you want.

Louis
  • 146,715
  • 28
  • 274
  • 320
  • Another interesting caveat @Louis: How do I ensure that `mocha --watch` re-parses _all_ my test files using the glob you defined above? When I run the test manually using either `npm test` or `mocha --watch`, all the test files throughout my infra are run the first time through, but when I edit any test while `mocha --watch` is enabled, only the first test file is re-executed... I keep my mocha flags in mocha.opts. – 4Z4T4R Oct 04 '17 at 20:02
  • 1
    @toszter I don't use `mocha --watch`. Maybe you hit a quirk of how it works. For instance, one of its quirks is that it does not detect if files are *added* to directories. I use `gulp`'s support for watching files, which starts Mocha from scratch each time it triggers so I dodge any quirk `mocha --watch` may have. You might be interested in [this comment](https://github.com/mochajs/mocha/issues/2928#issuecomment-319506273). It is from one owner of the Mocha repo on github. What I get from it is that the maintainers don't recommend using `--watch`. – Louis Oct 04 '17 at 20:10
  • How interesting... ok, well I am in the market for a simple solution to restart my tests every time I change a test case in my local development env, provided it won't take longer to set up than the cumulative time I will spend manually restarting my tests. `:P` I will give `gulp` a shot. – 4Z4T4R Oct 04 '17 at 20:14
  • @Louis doesn't work if the tests are three subdirectory down, e.g. app/abc/xyz/lmn/my.test.js – Nishant Mar 14 '18 at 06:23
  • 11
    @Nishant Globs will go down any number of subdirectory levels. The glob I've shown in my answer will match `src/app/foo.tests.js` and `src/app/x/bar.tests.js` and `src/app/a/b/c/d/baz.tests.js`. A common mistake people make is forgetting to (as I mentioned in y answer) quote the pattern. It ends up being interpreted by their shell, which may or may not work. The default setups of `sh`-type shells will screw up the pattern if it is not quoted. – Louis Mar 14 '18 at 10:29
  • 3
    Adding single quotes saved my afternoon. I have a structure where tests are nested differently inside the test folder, with some test files being in the root path of the test folder and others being inside subfolders as you mentioned in the comment above. – iomv Nov 27 '18 at 18:29
  • I got the result I needed with `mocha --recursive --extension tests.js` – David Carboni Mar 14 '23 at 15:00
0

Thanks @Luis. Single quote save here as well! "test:unit": "NODE_ENV=UNIT-TEST mocha -r ts-node/register 'test/unit/**/*.test.ts' --timeout 5000"

user3727540
  • 922
  • 3
  • 11
  • 30