Check out a free preview of the full Creating an Open Source JavaScript Library on Github course:
The "Exercise: Setting Up Mocha & Chai" Lesson is part of the full, Creating an Open Source JavaScript Library on Github course featured in this preview video. Here's what you'd learn in this lesson:

Mocha and Chai are unit testing and assertion libraries. In this exercise, Kent demonstrates how to get an initial test runner set up in the library. He creates an index.test.js file which will contain the test scripts and a mocha.opts file for configuring Mocha. The solution to this exercise is on the FEM/05.0-setup-tests branch. - http://slides.com/kentcdodds/write-oss#/8/1

Get Unlimited Access Now

Transcript from the "Exercise: Setting Up Mocha & Chai" Lesson

[00:00:00]
>> [MUSIC]

[00:00:03]
>> Kent C. Dodds: The next thing we're gonna talk about is testing. So how many people here have used Mocha before in their lives? Okay, sweet. Jasmine, anybody use Jasmine? What other, QUnit? Yeah, good old days. They're still running strong, right? So cool, yeah, so I prefer Mocha. I don't think I've ever used QUnit, actually, but I like Mocha.

[00:00:30] I also like AVA, AVA's great, too. I like Chai, when I use Mocha, it's really great assertion library, but you also have the expect library, that's a good one. So what we're going to use in this project though is Mocha and Xhai. We're only going to need a couple of tests because like goodness gracious we only have two points of contact with our API.

[00:00:52] And that's actually kind of an argument for micro libraries is that unique random array is so awesome because it is fully tested, 100% code coverage. So we can just use it and then we don't have to test it. We can just rely on that working and then we can test the stuff that is important to us.

[00:01:12] So, for this exercise, we're going to install those dependencies. Like I said, you don't actually have to do that because those have been installed for you already. But then we'll create a src/index.test.js, we'll create a test/mocha.opts to configure Mocha a little bit. And then we'll update our package scripts with test and watch:test.

[00:01:39] The watch:test being there so that we can do like TDD and stuff, which, is quite handy for developing libraries. So, any questions before we get into it? Okay, I forgot to do this. Any questions?
>> Kent C. Dodds: Okay, so actually, make sure that you're up to date on the linting branch before you get started, then we'll go ahead and create that new file, index.test.js.

[00:02:19] We're not actually going to test the library right here. We're going to get to a checkpoint and that checkpoint is, does my test runner work? So let me just review my notes here and make sure I don't get to far off of where we're going here.
>> Speaker 2: There was a question of why not just plain node assert?

[00:02:39]
>> Kent C. Dodds: Good question. Yeah, so actually, I'll just demonstrate node assert. That is a legitimate question. So we'll say const assert = require('assert'), then we can say assert(1 === 2, and 'one is not two...) like on of those, what on earth are you doing? And then I can just say node src/index.test.js and I'll get a failure.

[00:03:10] And so that's cool. There are a couple reasons that I like to have a testing framework and an assertion library together. So first the testing framework is nice cuz it gives you a watch capability, it gives you the ability to structure your test nicely, it'll automatically or it can run a whole suite of tests together.

[00:03:30] And then you can have it be running that whole suite in watch mode, and then just say, okay, I only wanna do this. So it comes with a lot of features, and the output is a lot nicer. And then on the other side of things, with just the assertions stuff, I like Chai just because I feel like it's more expressive than assert is.

[00:03:50] But if assert is your jam then like put it on a peanut butter and jelly sandwich. Just kidding, I don't even know it listen to it. I guess. Yeah, so good question. I think that's it's important to evaluate your options. Sweet, so let's do this. Actually, one thing that we're gonna do just first of all is I have, there's a plug-in for Mocha for ESLint.

[00:04:18] So we're gonna open up our ESLint RC file here, and we're gonna add kentcdodds/mocha. In which I configure the Mocha plug-in to make it a little bit nicer for us, and to make sure we don't make common Mocha mistakes. Then in here we're gonna say use strict and we'll add var expect = require('expect').chai.

[00:04:52] Goodness, yeah, I need to go to my package JSON. Actually no, sorry, nevermind. Don't worry about that. Okay so then we'll go to, the next line and say, describe, so we're using, yeah, Mocha global called describe, where we're going to describe the StarWarsNames module. And that will be described by a function that contains all of our test assertions in here.

[00:05:27] And our first test is simply going to be that it('should work'). So we're not actually going to test any functionality, we're just gonna make sure that we have mocha and chai set up together so that we can start testing functionality. So we'll say expect(true).to.be.false, we'll start out with a failing test.

[00:05:50] To make sure that our tests are like, it's capable for our tests to fail. And then, we'll fix it so that we know that our test can pass also. So, the next thing that we're going to do is we're going to configure Mocha. So, create a new file.

[00:06:06] Where that configuration file goes is in a test directory called mocha.opts.
>> Kent C. Dodds: So now you should have a test directory with mocha.opts. I never even noticed this, but I've got a sweet little icon there.
>> Speaker 2: [LAUGH]
>> Kent C. Dodds: I love that file icon thing, that's probably one of my favorite plug-ins, it's great.

[00:06:24] In here, the mocha.opts file, I don't wanna try and teach you too much about the testing framework because you might choose something else, it's not totally relevant. But if I were to just run Mocha on the command line, whatever I put in this opts file will be added to the command line arguments.

[00:06:41] And so, if I wanted to run the source index test file, I would say src/index.test.js. So, that's the file I'm always gonna run every single time I wanna run Mocha. So I'm just gonna stick that in here, so I don't have to type that anymore.
>> Kent C. Dodds: And with that configuration all tidied up, we're gonna just come over here to the right here, with the package.json, and I'm going to fix this test to just say mocha, use the mocha binary.

[00:07:25] And again, like I said when you ran the set up script it already installed mocha for you, so that's why we didn't need to install it. But if you want to, you can just type it in here. I think we're at 3.0.2 now. What you had installed was 3.0.0, so it looks like we may have a couple bugs in here, but I think it'll be okay.

[00:07:48]
>> Speaker 2: You look like you had completion on the on the version.
>> Kent C. Dodds: Yeah, I don't know what's doing that but I love it. I just noticed that yesterday cuz I normally don't like type versions in here, I normally just npm install. I have no idea what's doing that.

[00:08:02] But yeah, that's so cool.
>> Speaker 2: So it's actually reaching out to npm for that
>> Kent C. Dodds: Presumably yeah, I expect it probably has a cache or something cuz npm probably is not quite that fast but maybe so. So yeah now you can you should be able to say npm run test or pro tip npm test or another pro tip, npm t, all of those are the same.

[00:08:31] And you'll get a failure if you don't get a failure than something is wrong. Cannot find module expect. I know what's wrong, it's not called expect, it's called chai, sorry. So it should be you should be requiring chai and actually, it should be expect. I mixed those two things up.

[00:08:56] There we go, now you should get something like this. Does anybody need to see anything? Any files? Because I was all over the place.
>> Kent C. Dodds: Okay, let me pull up the questions here.
>> Kent C. Dodds: Okay, yeah, and Matthew got me, he got it. Okay, so great. Let's go ahead and fix this.

[00:09:26] We had this describe expect true to be false, we're gonna change that back to true or to what it should be, to true. And then now when we run npm t then it runs our tests, says it should work with a check mark and we're good. Anybody have that going?

[00:09:41] Yeah, raise your hand if you're online.
>> Kent C. Dodds: And with that actually I think we're pretty good, pretty set. We also wanted to add the watch command as well. Yeah, we got a couple of raising hands. Mocha is not defined for Ivan. Make sure that your set up script ran.

[00:10:11] If you're having trouble with Mocha is not defined, what you should check first is in your node_modules.bin directory, this will have a bunch of sim links that point to other files in your known modules directory. What you're looking for is a mocha, if you don't see that, then your install script probably didn't work for some reason and you just want to say npm install --save-dev mocha.

[00:10:44] Some more npm pro tips for you, save-dev can be shortened to -D, and install can be shortened to i. And if you like typing even less, then you can create an alias for npm install and just do ni, so I have an alias for that. Also, nicache, I have an alias for that.

[00:11:06] Here, I'll show you what that is. So it's npm install with a cache min and it'll hit the cache. So I can be totally offline and install stuff still. Just comes from my cache, which is cool. Okay, side note.
>> Speaker 2: That test file you had in your source, is there any reason to segregate that to a different directory?

[00:11:28]
>> Kent C. Dodds: Yeah, I was waiting for somebody to ask, cuz most people would put it in a test directory. So in a small library, there's really no reason to not do that. I just kinda do it out of habit. And the reason that I do that is in lots of applications, this is a library, but in applications, you'd have a source directory and a test directory, and they're supposed to mirror each other.

[00:11:54] And as the project grows, then you're like okay, I move to the controller to this directory, now I have to go to the test and move it to that directory. And so you wind up with a situation where these things are out of sync. Unless you write some tooling to ensure that they stay in sync.

[00:12:11] And so, it becomes harder and harder for new people to come into the library and know whether tests exist for the library or for the project. And so, I like to co-locate things and I have a blog post about this. Maybe somebody can look it up and put it in the chat.

[00:12:27] It's called what code comments can teach us about scaling and code base. That explains why it's a good idea to co-locate things. You can read that for more on that argument. Yeah, question
>> Speaker 2: Did you cover what's the difference between --save and --save-dev?
>> Kent C. Dodds: Good question, so it's basically whether or not it will wind up being saved to your dev dependencies or to your dependencies.