Unit Testing with Mocha and Chai [Part 1/2]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so in this tutorial we're going to take a look at unit testing with mocha and chai and this tutorial is really for anyone who's never written a unit test before so we're going to cover the basics of why you would unit test and then how you would do that with the mocker and chai libraries and we're using these rather than another framework like jest or cyprus simply because the syntax is quite easy to understand and there are a lot of organizations that will be using mocker and chai as their testing framework so it's good that you're acquainted with them so if you do take on a role where they're in use you'll have a good grasp of how they work so there's a link for the code for this video in the description below if you want to follow along and let's start writing our first unit tests with mocha and chai so in order to understand unit testing with mocker and chai we're going to set up a small project that has a few functions and then we're going to write some unit tests for them so the first thing we'll do if we head over to our package.json file you'll see we have no dependencies currently for this project so let's install the necessary dependencies that we're going to be using which is mocha chai and nice so we can simply write npm install and then use the save dev flag because we're going to save these as dev dependencies and then mocker chai and nice so that might take a minute or two to install but you can see the dev dependencies are now listed in our package.json file so let's quickly run through what each of these packages will do for us in this tutorial so mocha is the test runner so we use this to issue the commands to run the tests that we're going to be creating and chai is an additional assertion library which works well with maca and they're commonly used together and you'll see in a moment how that provides a bit more flexibility when we're writing our test cases and nice is a code coverage generator which will show us visually how much of our code has been covered by our unit tests so we're going to be writing our tests in a separate folder called test so let's create that now and then we can actually update our script section in our package.json file here you see at the moment the script to run our tests won't do anything but we can replace that with a call to mocker by just simply saying mocker test where test is the folder that's going to be holding all of our unit tests so if we go ahead and test that out now by simply saying npm run test you'll see the script runs but however there are no test files at the moment so we get this error saying that no test files are found so let's go ahead and create a test file now so in our test folder let's create a new file and we'll just call it app.spec.js so we give our test files a name that correspond to the actual source file that we're going to be testing so in this case we simply have the app.js file in our source folder so we name our test file app and the dot spec extension is optional but it'll just let other users know that this is a test file so if we go ahead and run mocker again you can see this time it passes however we get a result of zero passing tests because we haven't actually written any tests here so before we write our first unit test we just need to import a few dependencies so the first thing we're going to do is import assert which you'll see in a moment we'll use to make assertions about our test cases and the other thing we're going to need to do is import the function from our app.js file which if you look we simply have one function at the moment in there called add which takes two arguments and adds them together so in our app.spec.js file we can simply get the add function from the app.js file by referencing its path in the source folder so now we're ready to write our first unit test and we can write our unit tests with two functions the describe and the it function so you can think of the describe function as testing one specific function or a group of related functions and the ip function creates a specific unit test which is testing part of the logic inside of that function so i'm going to use the describe function to create a block of unit tests for the add function that we're importing from our app.js file so we'll say describe and the text in here can be anything that you like i'm going to describe the add function and then the second argument for the describe function is actually a function itself so i'm just going to put an empty arrow function in there the mocker documentation does discourage using arrow functions for various reasons but for our purposes in this video it won't cause a problem so inside here we're going to create an ip function and this is going to be the specific test that we're creating which is testing a part of the function so we'll say function the add function should add two numbers together because that's the purpose of the function and again we can pass another anonymous function into the second argument of the it function itself and here we need to write a test which will test the functionality of the add function so because we've imported it here on line two we can just call the add function by its name anywhere in this code so let's call it and save the result into a variable so we'll say const result is equal to add two and two so if we're adding two and two together we should expect the result to be four so we need to tell our unit test that that's what we're expecting for the result from the add function so we can do that by using the assert object that we imported on line one and we can say assert once say that we want to test for equality and the results that we got from our add function i want to say that's equal to four so the equal function on the assert object will take two arguments and it will check both of those arguments to see if they're exactly equal so if we run those tests again with our npm run test script you can see in the terminal that we're running one test and you can see it says the add function should add two numbers together as we wrote in our describe and it functions and you can see we've got a green tick because the result from the add function was equal to four so if we change the assertion and say that we're actually expecting the result to be 5 for example and then run that test again you can see that that test fails because we're expecting the result to be 5 but the actual result from the add function was 4. so this is the basis of all unit tests you're going to run a function or run some code that you've imported from your main source and then you're going to check that the result that you're expecting actually matches the result that the function produces so where does the chai library come into all of this well if we look at the assert object that we've imported you'll see there's various different functions on here to check the result from our add function we can say that it's not equal to or check its length for example so there are a lot of different functions which will allow us to control the assertion that we're making so let's actually import the chai library and there's actually one function that we want to import on there called expect so we can destructure that from the chai library and if we look down here now in our unit test we make a call to our expect function and we pass in the result and then if we look at the properties and functions that we've got available on our expect function you can see there's quite a few more different types of assertions that we can make providing greater flexibility in the kind of assertions that we can write and also the assertions that you make tend to read a little bit more like english than just using the assert object so for example if you wanted to recreate what we had before we're saying we expect the result and then we can say to be equal to four so if you save that and run the tests again you can see our tests are now passing again and we've rewritten our first unit test using the chai assertion library so you might be thinking well this is pretty obvious like obviously adding two numbers together will give you the result of four do we really need to write some code that will actually check that for us but where unit testing becomes really interesting and really useful is when you start thinking about all the types of ways that you can use the specific functions that you're testing like the add function in this example and seeing how it behaves when you pass in various types of data so for example with our add function it accepts two arguments but what happens if we actually miss out one of those arguments does it behave in the way we'd expect it to so let's write another unit test for that we should say it should be able to handle one number so for our result this time we'll say our result is equal to add and then we'll just pass in a value of two so there we've got only one argument passed to the add function and then we'll use our chi expect function to say we expect the result to be equal to 2 which is a fairly reasonable assumption if we're only passing in the value of 2 we should expect the result to be 2 and if we run our unit tests again you'll see the second test actually fails so here you can see we're expecting the result to be two but the actual value that we got out was not a number and that's because in our function of add we should find that the number of two gets populated into the a variable but the second argument b will be undefined and so if we try and add two and undefined together we get not a number so how do we make this unit test pass well we actually need to update our add function because it's not behaving as it should do so one solution would maybe to provide default values to a and b so that we don't get that undefined value if the user forgets to pass in two arguments so we'll say a is equal to zero and also b is equal to zero so if we don't pass in an argument for one of those now that will default to the value of zero so if we run our unit test again you can see that second unit test is now passing so that's just a small example of how you would use a unit test to actually improve the code that you've written let's go ahead and write a couple more so it should be able to handle zero numbers as well so if the user passes in undefined or those values get lost at any point when we try and call the add function so let's say const result is equal to add without any arguments and because those have been defaulted to zero for both a and b in the add function we should expect the result to be equal to zero and let's run our tests and there you can see the third test is passing as well so you might think our add function is pretty robust now but what about if we actually pass in other values that aren't numbers so for example if the add function gets accidentally called with a string so obviously strings added to numbers won't produce a very useful number so we should probably return like a default value like zero if we try and add a string to a number so let's write a unit test for that we'll say it should return zero if either argument is not a number and let's open up our function here so let's recreate that we'll say the result is equal to add and say if we try to add two to the word test so let's say we'll expect the result to be equal to zero so from those tests at the moment currently we won't get that result you can see the result we actually got was to test because the number two got changed to a string and then added to the test string so we need to update our add function to handle non numbers so one thing we could do in here is if we open this up and we could do a check in here to see if the arguments that have been passed in are indeed numbers so we could say if type of a is equal to number or we probably should say not equal to number or type of b is not equal to number then what we can do is we can return zero but if that's all good then we'll just return a and b so this way we're checking our arguments to see if they're actually numbers and if either one of them isn't we'll actually just return zero so let's run our tests again so you can see now the fourth test is actually passing as the add function is now returning a zero so if you want a little bit of practice at this point what you could do is create another function called sub or subtract and it'll do the opposite thing of add and taking two arguments and subtracting one from the other and see if you can write that function and then write the unit tests for it and see if you can think of all the expectations that might come out of that function and then use your unit test to expect those results and then check them by running the tests so if you had to go this exercise you might have ended up with something like this it's essentially just a copy and paste job from the add function and it's exactly the same function except on the last line we're actually just returning a minus b and the unit tests themselves we can pretty much recreate what we had for the add function so we have the same things where we should be able to sub two numbers together and get a result should be able to handle one number zero numbers and also if there is a non-number provided as an argument so if we go ahead and run those unit tests again you can see we actually get a failure and that's because in the sub function when we're handling just one number the first argument will actually get populated with two and then if there isn't another argument that will default to zero so we'll be actually subtracting zero from that so you can see the expectation that we might get minus two is actually incorrect so we can just update that and say we're expecting the result to equal two and you can see how that unit test was really useful i was making a specific assumption about that function that it would return -2 but the actual result was different so i can either update my unit test with the correct assertion or maybe i would go back into the app.js code and update the sub function so we also installed the nice library when we set up our project and the nice library allows us to have visual code coverage of what functions within our code we've actually written unit tests for so to run nice i'm going to create a new script so i'm going to go to package.json and i'm going to call the script coverage but you can call it anything you like and we're going to run nice and then the command i'm going to run is npm test so if we run npm run coverage you can see mocha runs again and runs all of our unit tests but this time we get some output at the bottom from nice that tells us what our coverage levels are so you can see in our app.js file we're covering all of our statements branches functions and lines which isn't surprising as our functions are fairly simple and we've written a decent amount of unit tests to cover all the different use cases another option with nice is to create a html output that you can view in the browser so when we run nice if we pass an option of reporter and set that value to html if we run our coverage again you can see we don't get that output at the bottom of the terminal but we've created a new folder called coverage which has in all our coverage in html format and if we just open up the index.html file you can see we have a nice web page that has all of our source files in this case it's just app.js and if we click on there you can see the functions that we've created and you can see the coverage levels for each of those functions so for example if we were to get rid of these unit tests for the sub function and rerun our coverage again if we go back to the html output you can see our coverage has dropped and also nice is highlighting to us the functions and lines of code which we haven't written unit tests for which is really useful if you're working on a larger project and you're not sure which functions and parts of your code have actually been covered so that's just a quick introduction to unit testing with mocha and chai hopefully you've seen the power of unit testing and how you can see that a simple function like adding two numbers together requires a little bit more thought when you're actually going to be using it in a real project of course when you're writing more complicated functions then you need to think of all the types of input the function can receive and all the different types of behavior it can have and write a unit test for each of those cases so that's it for this tutorial there'll be a second part to this where we'll actually cover more in-depth unit testing when you've got more complicated code that's asynchronous for example and we'll look at some of the libraries that you can use in conjunction with mocha and chai in order to create more effective unit tests you
Info
Channel: Junior Developer Central
Views: 9,731
Rating: 4.9560437 out of 5
Keywords: unit testing with mocha and chai, mocha and chai, mocha, chai, unit testing mocha, unit testing mocha chai, unit testing mocha chai tutorial, unit testing, javascript tutorial, javascript, testing with mocha and chai, javascript u, javascript un, javascript uni, javascript unit, javascript unit testing, junior developer central, unit testing with with mo, unit testing with moc, unit testing with moch, unit testing with mocha
Id: k4GFqgBR2qc
Channel Id: undefined
Length: 15min 41sec (941 seconds)
Published: Tue Sep 08 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.