“If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.” ~Gerald Weinberg I love testing. Quite early in my journey of learning to code, I heard of this “Test Driven Development” thing. Around the same time I was starting to expand the scope of my projects, and was running into very tricky bugs. Sometimes things that worked stopped working and I had no idea why. Testing only revealed more problems; my code was a giant tangled mess that couldn’t be tested. Testing my code has fundamentally improved my coding, and I hope this introduction helps you too. What I hope you’ll gain from this post: Setting up Mocha (a testing framework) and chai (an assertion library). Writing and running your tests. Synchronous tests. Asynchronous tests (callbacks). Some features I’ve used a lot (just so you know they exist). I’ll expect a very basic understanding of command line and npm. Setup First let’s make a new project. Create a folder and enter into the command line to initialize the project with npm. npm init -y Install mocha with the command below. or npm install mocha -g sudo npm install mocha -g And install chai with: npm install chai --save-dev Mocha is the framework that is used to set up the tests, run the tests, name the tests and do your tests housekeeping. Chai is an assertion library, meaning it’s the thing that you’ll use to check if things are doing what you . This will become more clear with the examples that follow. expect In your root directory create a file called . This will be the file we’ll test. Also create a folder called and put a file inside called . This file is where we will write the tests for . index.js test index.spec.js index.js Your project should look like so: ├── yourAwesomeProject/│ ├── index.js│ ├── test│ │ ├── index.spec.js│ ├── package.json Alright! We’ve done nothing, but now is a perfect time to make sure mocha is working. Type into your command prompt. mocha test Hopefully you get something like this -> 0 passing (3ms) You just ran the test runner! There are no tests there, but that doesn’t matter. We’ll fill it with tests soon enough. Writing your first test! Write the following code into your index.js. // Stubexports.addTwoNumbers = function (a, b) {return 0;} This function is called a “stub” function. This code doesn’t have any logic, but it still returns a number. This allows us to write a test for it without the hassle of trying to implement the function logic yet. Jump over to your index.spec.js file. I’ll show you the code, and then I’ll break it down. Make sure to type it out yourself. var index = require("../index");var chai = require("chai"); var expect = chai.expect; describe("index.js tests", function() {it("addTwoNumbers returns a number", function() {expect(index.addTwoNumbers(0, 0)).to.be.a("number");});}); To make sure everything is working, once again type in . You should get this cool snazzy output in your terminal: mocha test index.js tests✓ addTwoNumbers returns a number 1 passing (11ms) Everything is working, so let’s understand what we’ve written. The first two lines import your file which contains the function you want to test and which is the assertion library you previously installed using npm. just gives us a short way to call . index.js chai var expect = chai.expect; chai.expect describe() — Grouping a collection of individual tests describe(<Heading of Tests>,testsInCallback); Describe is like a heading. It’s a way to group a collection of tests together. You’ll notice in the above example, ‘index.js tests’ is the heading, and ‘addTwoNumbers returns a number’ is the ndividual est ( ) grouped with it. i t it it() — ‘Individual Test’ it(<Name of Test>, testInCallback); Every test assertion needs its own individual test. For example, to test that our function ‘addTwoNumbers’ can actually add two numbers, we should add at least one other test. We’re going to add another test: var index = require("../index");var chai = require("chai"); var expect = chai.expect; describe("index.js tests", function() {it("addTwoNumbers returns a number", function() {expect(index.addTwoNumbers(0, 0)).to.be.a("number");}); it("addTwoNumbers can add 1 + 2", function() { expect(index.addTwoNumbers(1,2)).to.equal(3); }); }); We’ve added it to the group “index.js tests’ demarcated by the describe function, and we’ve added it below the previous individual test. You’ll notice that the syntax used by expect is really easy to read. is how you check equality. If you are checking deep equality, for example to check if the fields inside objects are equal you can just add ‘deep’ to the chain like so: expect(<your function>).to.equal(<something>); expect(<yourObject>).to.deep.equal(<anotherObject>); The documentation for chai’s is clear and straight forward so I . expect recommend you take a look If you run now you’ll notice that you get a test failure. mocha tests index.js tests✓ addTwoNumbers returns a number1) addTwoNumbers can add 1 + 2 1 passing (19ms)1 failing index.js tests addTwoNumbers can add 1 + 2: AssertionError: expected 0 to equal 3+ expected - actual -0 +3 at Context.<anonymous> (test/index.spec.js:9:45) I find this information extremely valuable as it allows you to see what your expect actually returned (in this case a zero). Now that your test is failing, you can resolve it by fixing the code in your . I would usually write more tests, but you’ve now got a way to make sure what you’re doing works. This doesn’t make your code perfect but will allow you to at least have some peace of mind. index.js As a quick note, this technique is called “Red, Green, Refactor”. We’ve only covered the “Red, Green” part, but the idea is that you write a test that fails. Then fix your code to pass the test. Finally you can refactor your code with the peace of mind that you’ve got a test to check that your refactor doesn’t break everything. We’ve just spent the whole time so far with synchronous tests. But what if you need to test callbacks or promises? Asynchronous tests Testing asynchronous code is not difficult, but requires one additional piece of code that hasn’t been covered yet called . Without , mocha will dispatch your asynchronous code and continue without waiting for the assertion or execution of your callback. I’ll show you with a concrete example. done() done describe("Broken Async Code", function() {it('Async test', function() {setTimeout(function(){//failing testexpect(true).to.be.false;}, 1000);});}); The test above passes. This is because only fails a test if it catches the error from the . Because this is asynchronously executed (by a delay of 1 second), mocha skips over this as a passing test. We need to tell Mocha to wait by adding done. must be added as an argument and after the assertion. it expect done describe("Fixed Async Code", function() {it('Async test', function(done) { // Done added here.setTimeout(function(){//failing testexpect(true).to.be.false;done(); // Tells mocha to run next test.}, 1000);});}); You’ll notice that when you run , it’ll pause for 1 second and then give a failure. Sadly this isn’t the really detailed error that mocha gave earlier in the synchronous examples. This is solved by mocha’s built-in promises, but this is another topic and out of scope for this post. If you’re interested I recommend (it’s a really nice way of writing async tests with detailed responses). mocha test looking at this Some super useful features I use To run a single test or group just add to the end of or . Example: or .only describe it describe.only("index.js tests", function () { it.only("addTwoNumbers returns a number", function () { Investigate the following functions that can be used inside a block. , , , . These allow things to happen before and after each of your ndividual ests. (Good for set up and clean up) describe before() beforeEach() after() afterEach() i t Mocha can be used in the browser! It loads up a cool web page with a todo list style format with all your tests. (This makes testing web pages far easier). Good luck. And remember that testing is a skill, so practice will make perfect. :) is how hackers start their afternoons. We’re a part of the family. We are now and happy to opportunities. Hacker Noon @AMI accepting submissions discuss advertising &sponsorship To learn more, , , or simply, read our about page like/message us on Facebook tweet/DM @HackerNoon. If you enjoyed this story, we recommend reading our and . Until next time, don’t take the realities of the world for granted! latest tech stories trending tech stories