Test-Driven Development // Fun TDD Introduction with JavaScript

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
red green refactor imagine you're sitting in a technical interview for an entry-level web developer job and they ask you to implement a dynamic time warping algorithm to measure the similarity between two sequences in logarithmic time instead of freaking out and wondering what this has to do with jquery you can just say no problem let me write a few test cases for that first not only will that buy you some time but it also makes you look like you know what you're doing test driven development is a technique where you describe the behavior of your code before you go and implement it if you trust the science testing will help reduce bugs and improve the maintainability of your code base in the long run and if you're new to programming knowing how to test your code is one of the most powerful ways to level up as a developer not only is it fun but it will also teach you about your code in unexpected ways and make you much better at debugging it today's video will teach you everything you need to know to get started with software testing as a developer we'll talk about a bunch of different testing strategies from a high level then take a hands-on approach by implementing unit tests from scratch with jest and we'll also look at end-to-end testing with a tool called cypress but most importantly by the end of the video you'll learn why testing is valuable and how to make the decision about whether or not you should test something because it's a practice that walks a very fine line between being valuable and a complete waste of time before we get started make sure to hit the like button and subscribe in the last video i explained how software testing works but if you missed it automated testing is basically just a way to write code that describes your requirements and validates your main application code now most developers i know and myself included generally don't start writing tests until we have a working feature or maybe we just don't write any tests at all and that's especially true with front-end development because ui requirements tend to change frequently but if you follow the principle of test-driven development you'll write your test before you implement your actual code and a common mantra is red green refactor which means you write a failing test first red then you write some code to get it passing green then you go back and optimize or refactor the code it's not always practical to do this but if you have a project with very clear requirements you might find that tdd actually improves your productivity now let's take a look at a bunch of different testing strategies and see how they add value to a code base at the lowest level we have unit testing where the goal is to validate the behavior of individual functions methods or just units of code we'll get hands-on with unit testing in just a minute the next level up is integration testing which involves testing multiple units of code together for example you might have a react component and a hook to fetch something from a database you can unit test each of these individually but then have an integration test to see how well they work together like is the component actually able to use the hook to get the data that it needs for the ui from there we have end-to-end testing which runs your app in a simulated environment and attempts to emulate actual user behavior there's a really awesome tool called cypress that has a browser-based test runner that allows you to program tests where users click on buttons fill out forms then assert that the actual changes to the dom or the ui are valid personally i find end-to-end tests to be the most valuable ones that i write so make sure to stay tuned until the end of this video to see cyprus in action in my opinion these three testing strategies are the most important ones to know but there are a lot of other terms that get thrown out there that you may want to be familiar with acceptance testing is a form of testing that makes sure that the software meets all of the clients requirements then you have system testing to ensure that everything works on actual servers or hardware then you have things like sanity or smoke tests on a large application you may have thousands of tests to run and this can actually take a very long time and delay everybody else's work a smoke test runs a few of the most important tests first to make sure the app isn't on fire before proceeding with the rest of the test suite now at this point we've only looked at functional testing but there are also non-functional tests for things like performance usability and security you'll often hear terms like stress testing or failover testing which are used to test the capabilities of the infrastructure as opposed to the code itself now that you know what all this fancy testing jargon means let's get our hands dirty in javascript by pretending that we're in an actual technical interview we're required to implement a stack data structure where the last item in is the first item out it's very similar to an array but we have to implement it without using a javascript array now before we can start we need to initialize a project and keep in mind that you can find the source code for this on github i'm using veet by running the npm init vjs slash app command then selecting the vanilla javascript option that gives us a simple project to get started in then i'll add the jest testing framework to it by running npm install jest which itself will be looking for any files in your project that end in dot test.js let's go ahead and create a test directory then add a testing file to it to keep things simple i'm going to implement our code and also test it in the stack.test.js file now to run the code in this file we need to execute the js testrunner we can do that by going to our package.json and setting up a new npm script called test that runs the jess command in addition i'll add the watch all command to have just watch our code in the background and rerun the test anytime it changes and also the verbose flag to add some extra output to the terminal go ahead and run npm test from the command line and you should get your first failing test because it's detecting that file but we haven't actually written any code there yet one other optional but highly recommended thing we can do here is add types to the project to give us intellisense for all the matchers built into jest install the types using npm then create a jsconfig.json file that has a type acquisition property for jest this will allow vs code to provide intellisense for everything built into jest making your life way easier one other random pro tip i'll throw out there is that you may also want to install the wallaby plugin it's a paid vs code extension with a free trial but it will tell you whether or not your tests are passing directly in the editor without having to look at the terminal and that can give you a really nice productivity boost i'm going to use the terminal in this video but wallaby is nice enough to provide us with a discount so feel free to check that out in the description below and now we're ready to proceed with our interview the first thing i'll do is use the describe function to describe the thing it is that i'm testing which in this case is the stack it takes a callback function as the second argument inside of which we can define multiple individual tests by using the test function or it both of which do the exact same thing we'll create a very simple test suite here with only three requirements we'll want to make sure that our stack is created empty that it can push items to the top and it can also pop or remove items from the top at this point if we go ahead and save the file we should get a failing test suite because we've only described our requirements and haven't actually implemented any testing code yet in some cases you may want to hold off on the test implementation in which case you can use the to-do method to make the test pass while you figure things out now let's go ahead and implement our first test the main goal of the first test is to ensure that our stack can be instantiated with a valid state let's go ahead and instantiate a class that doesn't exist to represent the object that we want to test from there we'll use expect to write an expectation to make sure that our code does what is expected it should have a top property that represents the index of the item at the top of the stack because it's empty when it's first created the value should be negative 1. 2b is a matcher that will test the actual value to the correct value now here's where test driven development starts to get really cool go ahead and save the file and you'll notice that we get a failing test if we look at the output closely it'll tell us exactly which line of code failed and why it says reference error stack is not defined we can use that feedback as a starting point to start implementing our code to address the error we'll first need to define a class called stack go ahead and define it then save the file then you'll notice that we still get a failing test but this time it goes down to the expectation telling us that it expected negative one but received undefined as the return value to address that issue we need to add a constructor to the class to initialize it with the proper data let's give it a top value of 0 and then we'll also define an items property here to represent the stack itself as an empty object because remember we're not allowed to use arrays in this problem go ahead and save the file and now we finally get a passing test you can also add multiple expectations to a single test let's go ahead and test the stack items property to make sure that it's an empty object but when we do that you'll notice that we now get a failing test even though we're definitely comparing an empty object to an empty object and it's actually not an issue with our implementation but an issue with the test itself the 2b matcher checks for referential equality between two objects in this case both objects are empty but they're two different objects in memory which is causing the test to fail what we need to do here is use a different matcher the two equal matcher would be a better choice because it checks for value equality instead of the object reference itself an important takeaway here is that it's not always your main application code that's the problem it might be a bug in the test itself and unfortunately we don't write tests for our tests now let's move on to our second test to see if a stack can push an item to the top what you'll notice is that the first thing i'm doing is initializing a new stack just like we did in the previous test but there's actually a more efficient way to do this jest has a set of helper functions for setup and tear down these are really useful because code duplication can get really bad inside of a test suite for example we might set up a global variable for the stack then use the before each hook to re-initialize it before each new test that'll give us an empty object to work with before each test so we don't have to set it up manually in each one now going into our second test we'll call the push method with an item and then we'll expect the top value to be incremented by one and we'll add a peak property to get the top of the stack and we'll expect that value to equal the value that we just pushed to it that'll give us a failing test and then we can once again go into our source code and start implementing the features needed to get to a passing test in general what you'll want to do here is try to get to a passing test as soon as possible once you have that passing test you can then go back and refactor and look for optimizations to make while trying to keep your test in the green there's just something very psychologically satisfying when you go from a red failing test to a green passing test my challenge to you is to now implement the final requirement in the test suite try to use test driven development to implement a feature that can pop an item off of the stack speaking of psychologically satisfying another thing you can do is run a code coverage report which will give you an idea of how well your tests cover your actual source code back in the package.json add the coverage flag to the jest command rerun it then you'll get this report generated that tells you the percentage of code covered by your test suite that can be useful at times but mostly it just gives you a false sense of security 100 code coverage doesn't mean that you have a good test suite but it may be a good thing to show your product manager or client what i want to show you next is a lot more fun and interesting and that is end-to-end testing unlike a unit test which is designed to be fast and simple an end-to-end test is very long and complex and takes a while to run because it simulates actual user behaviors in the browser we could write our end-to-end test with jest utilizing the puppeteer package however my favorite way to write end-to-end tests is with a tool called cypress install it by running npm install cypress and this will take a few minutes because it's downloading an actual browser that will run your tests in a real world environment when the installation is complete we can go into our package.json and add an end-to-end script that runs the cypress open command that should open up the testrunner which comes with a bunch of built-in examples if you click on the actions example you'll notice it starts running a test suite by filling out a form clicking on buttons and doing all kinds of other stuff when i use cypress for my own projects i use the firebase emulator to create a mock database and mock user authentication which allows me to test my apps efficiently in an environment that is very similar to how they'll look in production now if we go back into our source code you'll notice that a cypress directory was created we can find the source code for this example test by going to the integration folder to the actions.spec file and just like in jest we first define a test suite then inside of it we have multiple tests with the it keyword now the cool thing about cypress is that it makes it very easy to code these automated interactions with your website it has a jquery like syntax that allows you to match a dom element like say a form input then type into it with whatever text you provide you can then run expectations with should to ensure that it has the proper value css style or whatever else is important in the ui it's a really awesome tool and i'm not sponsored by them in any way but i'm going to go ahead and wrap things up there if this video helped you please like and subscribe and consider becoming a pro member to get access to more advanced content thanks for watching and i will see you in the next one
Info
Channel: Fireship
Views: 195,722
Rating: undefined out of 5
Keywords: webdev, app development, lesson, tutorial
Id: Jv2uxzhPFl4
Channel Id: undefined
Length: 12min 54sec (774 seconds)
Published: Fri Jun 04 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.