Unit Testing in Javascript | Writing Automated Tests With Jest

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
but i'm a developer i know how to write code and when something becomes mundane and i don't want to do it i can write some code to automate that process for me and this is what we're going to do with tests we're going to write code that automates this testing process for us [Music] in this video i'm going to explain the benefits of writing automated tests and i'm going to show you how to write automated tests for a basic javascript application right now i have a really basic express application that has a single post request to users to create a new user object and when this post request is made it should include a username and a password so that a new user can be created and at some point within this function we should validate the username validate the password make sure they meet some sort of criteria and then probably save that user to the database and then send a response back to the client for this video i want to focus on the validate password part of this function so we're going to make sure that the password is you know at least like eight characters long and has a number and a letter and whatever and then if the password is valid uh this valid password variable will be set to true and then based on whether it's valid or not we'll send either there's a valid user back to the client or we'll send an error saying it's an invalid password so i need to write all of the logic to make sure that we actually validate the password and then whatever the outcome of that logic is uh this variable will either be set to true or false and then we'll send a response back to the client and right now i have a basic html page setup that has a username and a password field and if i enter this right now it's not going to do any logic it's just going to take the the true value here and send back a success response so it says if the password is valid even though there's nothing actually there yet and then if on the server i just change this to false then signing up will say it's an invalid password so i can use this to test whether the function i've written for the password validation actually works or not and for this code to validate the password here i want to make sure that the password uh is at least eight characters long um has at least one letter and maybe at least one number so this is the criteria for the password if it meets all of these criteria then i will set valid password to true otherwise i'll set it to false and that's pretty much it for now [Music] so first i'm just doing a check to make sure the password length is greater than or equal to eight then i've created a string that contains every letter in the alphabet and i'm looping over every single character in the alphabet and checking if the password includes any of those characters that'll tell me if it has at least one letter and then i'm doing basically the same thing but with numbers instead of letters and that will tell me if it has at least one number so if it has a number has a letter and is a valid length then it's a valid password otherwise it's an invalid password so uh it's a really basic implementation um and i'm pretty sure this works but in order to know if it works i should test this so if i input well nothing it should be an invalid password if i input something that's like eight characters long but doesn't contain a letter then it's still invalid if i do eight characters and it contains a letter it's valid and if i go longer still should be valid so this seems to be working right now but to make sure this function actually works i'm having to manually test it i'm having to manually come into this web browser enter in different passwords and tap this button every single time i want to know that my password validation function is actually working and this isn't super ideal because it's very manual it can take a lot of time and every single time i need to make a change i'm gonna have to come in here and test all of these cases again just to be confident that it's still working and this might not seem like a huge deal right now but this can get out of hand really quickly so right now uh this works with uh case letters and numbers but if i were to try an uppercase letter this doesn't work because i'm only checking for these lowercase letters here so i could create maybe another loop maybe an uppercase alphabet or maybe i could just uh convert the password to lowercase before doing that check to make sure that it gets like any lowercase letter here but this logic was just working a moment ago and i've now made a change and i'm not sure if this change might break some things surrounding this function here so if i save this and go back to the browser i'm pretty sure this should be working now so if i click sign up it's a valid user but again you know i'm not sure if i may have broken the lower case letters now so i'm gonna have to go back and check those cases as well okay that still works so i haven't broken the lowercase or uppercase thing these are all working now but i'm still having to check those multiple cases because i made a small change and this is just for a sign up form where i can get to the form immediately but if i was doing some sort of validation or logic uh maybe on like a social media app where someone has to sign up then log in then create a post and then maybe create a comment on a post and i'm doing some sort of validation on the comment that's a lot of steps to have to manually go through just to check that a small piece of code is working that maybe a small piece of validation code is working so this is not an ideal solution to testing your code it's very manual and if i am a human i'm having to test my code i don't trust myself to test every case over and over again every single time something changes so i'm probably going to end up with bugs in my code and that is not what we want when we're writing code but i'm a developer i know how to write code and when something becomes mundane and i don't want to do it i can write some code to automate that process for me and this is what we're going to do with tests we're going to write code that automates this testing process for us and there's lots of different types of tests we can write to automate this testing process i could write some code right now that goes into the browser fills out a username and password in here clicks this button for me as if it were a human being and then checks this piece of text right here to make sure that it's valid when it's a valid password or maybe uh invalid password when it's invalid and these types of tests where it's acting as me and inputting data and clicking buttons can be really useful but i want to specifically just test the password validation if i test it using the form uh there could be something wrong with my client-side code there could be something wrong with my network connection there could be something wrong with my server-side code and any one of those would cause my test to fail even if my password validation logic is in fact working so i don't want to write this type of test i just want a test that tests this small piece of functionality the actual password validation code which is just from line 16 to 35 here i don't care about anything else right now i just want to test this small piece of functionality to make sure that this works and this type of testing is called automated unit testing and you'll hear unit testing used to refer to all types of testing but really it's for testing a small unit of your code whatever that kind of means but i'm just going to be focusing on this small piece this password validation stuff and right now this is just dumped straight into my post request function which has a lot of server-side code surrounding it it's a bit noisy in here so in order to actually test this piece of code just from line uh what was it 17-35 the first thing i want to do is actually take this code out of this function and put it somewhere where it can just be sitting alone where i can just test this bit of code without anything else and in javascript the way i can do that is just by creating a function so i call this uh validate password and if i actually pass the password to this function this function can stand alone it isn't dependent on anything other than a password being passed to it and if i just return valid password at the end return valid password then i can just call this function pass it any piece of text and it will tell me if that piece of text is a valid password or not so in here um i'll just say const valid password equals validate password password okay so i've got all my post request code in here the request comes in i respond to that request and i'm just calling the function and keeping all of this logic separate so now that i've separated this out i'll be able to test it a little bit more easily but i want to take this one step further because this is in my server.js file which is responsible for all my server-side code but this validate password function really has nothing to do with server-side code it's just validating a piece of text so i'm going to take this out of this file just cut it and create a new file and i think i'll just call this validate password.js and just dump it in there and now if i just module.export equals that there we go uh then in my server i can require that and then i can still use it in the exact same way and if i go back to the browser i'll even be able to test okay that's an invalid password that's a valid password so everything's still working the same way but i've taken that function out i've put it in its own file and this is going to make things much easier to test and it also just makes the code cleaner and easier to refactor in the future so it's just a good step to take overall so now i actually want to write some tests for this function and usually we'll do this by creating a brand new file that just contains our tests and the naming convention for this will be validate password so the same name as the thing that i'm testing but then dot test dot js and now i have a javascript file just a normal javascript file where i can put a bunch of test code for this function and the first thing i need to do is import this function validate passwords and now i just need to write some code that tests that it's working correctly um so i can just do this in the way that we're already used to testing our code with some console logs so if i call validate password and for example i put in an empty string i'm going to expect this to return false this is not a valid password uh so i could just write a couple of things like this like if i put in one that doesn't contain any numbers um that's going to be false if i put in one that only contains numbers that's gonna be false uh if i put in something that is at least eight characters but contains number and letters that's gonna be true um so i could just console log these out let's see you go to terminal node validatepassword.test.js and now i'm testing all of those cases and all i have to do instead of like clicking that button and seeing the response come back from the server i could just scan through this and be like okay the first three was supposed to be false and the last one was supposed to be true so that's actually working that's cool um i could take this one step further actually i could say that i'm expecting the return value of these ones to be false so i'll just do a quick check triple equals check or false rather equals true so now when i run this file i just i'm expecting to see a bunch of true values because i'm doing a check to make sure it is this value so this should console.log true just over and over again there we go um and i can really put in as many tests as i want here and i can just see true print it out over and over again and if i ever see a false i know that something is not working and this is the idea behind automated testing i can have some code that runs my production code over and over again with many different cases and i'm just trying to make sure that the result of running that code is what i expect it to be and in this case it's either going to be a true or false value i'll actually add a few more tests in here just to make sure it works with uppercase maybe uppercase and lowercase um and i can run this okay everything seems to be working so this is a huge improvement from my system of going into the web browser clicking the button and testing each thing individually and i could go in and i could refactor that password validation code and just rerun this file and see if things are working or not just by checking for true values but i actually want something even better than this i want my tests to actually tell me which things are passing and if anything's failing which things are failing and if something is actually failing i want as much information as possible about that failing test so that i can go in and fix whatever is failing i want to be able to write multiple tests for all of my code within my application and run them all with a single command see how many tests are passing how many tests are failing i want to push my code to github have github run my test for me and if all of my tests pass actually push my code into my production servers so that users can actually use my new code and i can get all of these features and even more just by using a testing framework instead of my console log statements and this being javascript there's obviously tons of testing frameworks so i'm just going to go with the most popular one right now which is jest so i can mpmi-d uh just installing it as a development dependency and you don't have to use jest you could use any of the other testing frameworks like mocha but just being very popular right now means that there's lots of documentation on how to use jest it also is the default testing framework that comes installed when you create a react app so if you're working with react and you want to be able to write tests really easily it's already there and you just start using it so jest is a pretty good option for test frameworks now that i have just installed i'm going to modify this test code to be compatible with jest [Music] so when we're using jest we wrap each of our tests inside of this test function and the first thing this is expecting is a string and that's just a plain bit of text that describes what this thing is testing and we can write this however we want but the point of this is to describe what is being tested so that when we run the tests the logs will actually tell us which tests passing which tests are failing and when we come through and read our tests later on they act kind of like comments they're just telling us exactly what's going on here then within this test function it accepts a callback function where we can actually put some sort of assertion and when we're using jest we get built-in matches that allow us to write our assertions in this type of format where we can say expect some value to be something else and there's a bunch of different things here and i'll leave this documentation in the description but we use this to assert that our code is actually working correctly so i've written out all of these tests for jest and to run these tests i just go back into terminal and i can run mpx jest and this will test every single test file in my project or if i just want to test a specific file i can go validatepassword.test.js and now jest will run all of the tests in this file for me and will give me the output of what is going on so here are all those bits of text that i put into those test functions so here's exactly what is being tested and at the very end of this it tells me one test suite pass so that's that single file there were seven tests in that test suite and all of those passed and it took 1.411 seconds to actually run all of that so here i now have a similar thing that was going on before but i just run that really quickly and it tells me immediately if things are working or if they're not working and if this were to fail for some reason let's say i go into validate password and um i don't know i accidentally remove this carelessly so now it doesn't test for uppercase letters as well if i come back into my test suite and just run that single command it's going to immediately tell me which things are passing which things are failing so this one failed right here it should return true for a password with numbers and uppercase letters and eight characters or more but it actually failed and why did that fail well i can just go into the function and see maybe something went wrong there and i know that i'm not checking for uppercase characters or making sure they're lowercase before i do the check so then i can make that change come back in run the test suite and hopefully all of these pass and now i know my function is working so now i want to take a look at the best benefit we get from having a test suite like this so if i have tests i know that i can just run a script to see if my code is working and i have this function and it's you know it's not too complex but it's like kind of big i guess uh looks maybe a little bit messy if i were to refactor this i would be terrified that i was breaking something i know this works so i don't want to change the code in here because i don't want to break anything in my app but refactoring is good it allows us to clean up our code it allows us to make changes and we need to be able to make changes in our code so having a test suite gives me confidence in actually being able to change my code whenever i want and for this code i'm not going to make any huge improvements here but i could reduce the number of lines of code here just by using a regular expression so [Music] i actually don't think i need these comments as well because i think this code kind of describes itself like checking if it's a valid length as letter has number and returning all three okay so i've shortened this function up i wouldn't necessarily say this is a huge improvement but i do like that it's fewer lines of code and i like simple regular expressions like this when they don't get too complex so i'm happy with this uh but how do i know if it's working or if it's not working well i have that magic little script where if i just run this i'm immediately going to know if i have broken something or not and i just happened to not break anything this time which is fantastic so there i am now able to update my code and know if it works or doesn't work immediately by running that single script that's it for this video that was a look at why we would want to write automated tests and how to write automated tests in javascript using the jess framework in my next video i'm going to talk about test driven development which is a technique that takes automated testing to a whole nother level so stay tuned for that in the future or if you're from the future check it out right now
Info
Channel: Sam Meech-Ward
Views: 3,890
Rating: undefined out of 5
Keywords: jest, javascript, mocha, tdd, javascript testing, web development, unit testing, js testing, jest tutorial, jest testing, javascript unit testing, jest framework, js unit tests, js testing jest, unit testing javascript, javascript tdd tutorial, node testing jest, node testing, express testing with jest
Id: hz0_q1MJa2k
Channel Id: undefined
Length: 18min 52sec (1132 seconds)
Published: Sat Mar 06 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.