Which Test Framework?
Published: 2021-10-15 23:29:16

I'm going to keep this short, sweet, and very opinionated. I recommend you do your own research but for those looking into testing JavaScript or TypeScript I hope to help with a very high level overview. Also a disclaimer that this is the web, check the dates on your sources, this article might be obsolete tomorrow :)

So you're choosing a testing framework, which to choose? What are the kids using these days?

(Ranked by popularity, not by my personal preference)

# #1 Jest 
Creator: Facebook 
Weekly Downloads: 13,942,759

Pros: 
  Most popular
  Good tooling / plugins for IDEA, VSCode, CLI

Cons:
  NodeJS only, if you want to run Jest in a browser it takes considerable effort with puppeteer. Jest-puppeteer is poorly maintained.

Overall:
  Jest is great for unit tests. My staunch opinion is that code written for a browser should be integration tested in a browser. This is at the very least more difficult to do in Jest than Mocha or Jasmine, so this is a non-starter for me.

Jest has batteries included, that means it is full-featured in that you get a test runner, assertion libraries, and many utilities like mocking, spies, time harnesses, asynchronous testing, you name it. 

# #2 Mocha
Creator: OpenJS Foundation
Weekly Downloads: 5,293,954

Pros:
  Works well with Node and browsers
  Has good tooling for IDEA, VSCode, and CLI
  
Cons:
  Requires additional libraries for everything. Typically chai for assertions, sinon for mocking.
  Chai syntax is obscure and hard to remember.

Overall:
  If you want to get started with mocha, you'll need a combination of libraries, for example `npm i -D mocha chai sinon chai-sinon`
Besides a more complicated setup, Mocha, or more specifically Chai, in my opinion, takes behavior driven development a little too far. When building your assertions in Chai there is this chaining syntax that's meant to be a human language to your tests. For example instead of: `expect(undefined).toBeUndefined()` it's `expect(undefined).to.be.undefined`
or instead of `expect(foo).toEqual(bar)` it's `expect(foo).to.deep.equal(bar)`

This can lead to easily made mistakes in your tests. `expect(foo).to.be.defined` will always pass because `defined` doesn't exist. Instead you should have written `expect(foo).to.not.be.undefined`, which IMHO is insane. 

# #3 Jasmine
Creator: Pivotal Labs
Weekly Downloads: 1,865,652

Pros:
  Very similar to Jest
  Batteries included
  Works out of the box in Node and a browser

Cons:
  Not _quite_ Jest
  Ugh, what is that color, cannon pink?
  IDEA extension needs work

Overall:
  This framework feels like it's trying to be Jest; the syntax is almost identical, and except for a couple nitpicks, Jasmine is succeeding. Being able to run in a browser out of the box is the real selling point here. I can create selenium tests that execute my Jasmine unit and integration tests in a headless browser for continuous integration, and I can create a static page that can run my tests on any device with a browser. 
The IDEA extension needs to add debug support, debugging unit tests is a must-have for me and the only way to currently do this with Jasmine tests is to debug the main npm run test task.

__________________________________________________________

TypeScript Notes:
They all work with TypeScript, but with some additional work.    Namely, you have to register something like ts-node to transpile at runtime.
Example:
`npm i -D ts-node`

In your run configuration template:
Node options: `-r ts-node/register`

Jest with React has a project creator that can set things up for you out of the box. This is great if you're using React :)

__________________________________________________________

# Bottom Line

You do you, mang. 

I'd use Jest if it had browser support (Puppeteer doesn't really cut it for me.) Maybe there's a better way, let me know :). Until then, Jasmine has been great!