I invested a reasonably substantial amount of effort in learning to use the Mocha testing toolchain in JS only to find I don't think I like it.
This is to store/share my thoughts outside of the repo in the event I ever want to revisit it
The reason I do not like Mocha is it has been very piece-mill and feels cobbled together. It seems logical they would have bothered improving their built-in library, or making a very simple straight forward way to incorporate Chai, for example.
Also, the TypeScript support feels like a second-rate hobbyist support riddled with incomplete features. I may have this totally wrong, just expressing that's what it came across as.
Critically, it began to feel very magical and too implicit rather than explicit. The docs didn't seem to actually express the way to use the API and focused only on obscure example usage, which seemed consistent across the entire toolchain (to be fair, maybe that's a problem inherent to the weird way JS frameworks stitch together).
I tend to dislike magical implicit behavior as it removes control from the dev and makes debugging much more difficult. This is the primary reason I didn't care for the toolchain.
Anecdotally, I have noticed most mocha usage and recommendation seems to come from people who have used it all along. I happen to begin on the Jest side of things, but hadn't realized the friction with setting up and using the Mocha toolchain until trying it directly
Mocha - JS Unit Test framework
Chai - Assertion framework, not Mocha specific but also unneeded for Jest
Sinon - Mocking and stubbing framework
Istanbul/NYC - Code coverage calculation (Jest builtin)
Typescript specific
npm install [--save-dev] typescript ts-loader ts-mocha @types/mocha @types/chai
npm install [--save-dev] mocha
- https://typestrong.org/ts-node/docs/recipes/mocha/
- https://github.com/mochajs/mocha/blob/master/example/config/.mocharc.yml
Config: package.json
"scripts": {
"test": "ts-mocha",
"test-watch": "ts-mocha -w",
"coverage": "nyc npm run test"
}
Config: tsconfig.json
Add @types/mocha
to types
Filename .mocharc.yml
extensions: ["js", "jsx"]
watch-files:
- src/**/*.js
- test/**/*.js
spec:
- src/**/*.spec.{js,jsx}
- test/**/*.{js,jsx}
Does not appear to treat the multiple file extensions as expected. At times, simply changing this to a strict definition would fix failing tests.
Filename .nycrc.yml
extends: "@istanbuljs/nyc-config-typescript"
all: true
cache: true
clean: false
babel-cache: false
report-dir: ./.coverage
include: ["src/**/*"]
exclude: ["src/**/*.spec.js", "src/**/*.spec.ts"]
ignore-class-method: ["render"]
excludeNodeModules: true
check-coverage: false
branches: 80
lines: 80
functions: 80
statements: 80
Config: launch.json
{
"args": ["--timeout", "999999", "--colors", "${workspaceFolder}\\test"],
"internalConsoleOptions": "openOnSessionStart",
"name": "Mocha Tests",
"program": "${workspaceFolder}\\node_modules\\mocha\\bin\\mocha",
"request": "launch",
"skipFiles": ["<node_internals>/**", "**/node_modules/**/*"],
"type": "node",
"stopOnEntry": false // Enable if want to enter breakpoint immediately
}
Mocha sidebar extension was recommended on the Mocha website, but not great. Has partially implemented coverage tool and lots of difficult to understand explanations.
For example, the breakpoint toggling was described as having a "known issue with code coverage, use F9". I was fortunately able to deduce what was going on, but I was better off having identified that workaround myself than to be lead astray by the strange explanation.
All that aside, this is how I configured. Keep in mind that the Mocha sidebar extension's configuration for Mocha is completely detached from VSCode's Mocha config. So, one of them can work while the other isn't, for example. This happened to me many times and made troubleshooting frustrating.
Config: settings.json
"mocha.files.glob": "test/**/*.ts",
"mocha.files.ignore": "**/node_modules/**/*",
"mocha.coverage": {
"enable": true,
"decoration": true,
"runWithInterval": false,
"autoUpdateInterval": 20000,
"activeOnStart": true,
"runAfterTest": false,
"runCoverageAfterFileSave": false,
"reporters": []
},
"mocha.requires": ["ts-node/register"],
"mocha.logVerbose": true,