Testing Angular 2+ Apps with Jasmine and Karma | Mosh

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Good stuff, his courses are really good.

👍︎︎ 2 👤︎︎ u/ckelly365 📅︎︎ Feb 02 2017 🗫︎ replies

uptoot for mosh. His videos are the best

👍︎︎ 1 👤︎︎ u/beararmedrobbery 📅︎︎ Feb 02 2017 🗫︎ replies
Captions
[Music] in this section you're going to learn how to write automated tests through angular2 apps whether you're an absolute beginner or have some experience in automated testing I'm going to take you from the ground and teach you how to write automated tests for your angular apps so I'm not assuming any prior knowledge of automated testing so we're going to start with a quick introduction to automatic testing its benefits when to use it and why then we're going to look at different types of automated tests their pros and cons and then we'll get into the mechanics we're going to start with a few simple examples and then as you go through this section the examples get more and more complex these examples are based on the patterns that you see in a lot of real-world applications so for each pattern I will show you what you need to test and how to do it next I'm going to show you how to find out how much of your code is covered by tests and finally at the end of the section I'm going to give you some exercises to put what you learn in practice so there is a lot to cover now let's get started so what is automated testing is it a replacement for manual testing do I really need it how should I do it actually write my tests first which we call test-driven development or should I write the application code first launch I don't know what to test these are the questions that a lot of beginners - automatic testing as well as developers who have some experience having their head so let's start with the first one what is automated testing automatic testing is basically the practice of writing code to test our code and then run those tests in an automated fashion so here is an example imagine we have this function somewhere in our application it's a basic calculate function it takes an input and depending on some conditions and return different values now in light of this function is used somewhere in the application with manual testing we have to launch the application in the browser perhaps you have to login for maybe do a few clicks here and there to get to the target page then we have to enter value us into a few formfields so eventually this function is called now this is very time-consuming this whole cycle to execute this function in a manual fashion may take 30 seconds overtime with automated testing we can write code and directly call this function with different inputs and then we can run this code in an automated fashion and this may take only a fraction of second to test this function with different inputs so with this practice we can test a large part of our application functionality and maybe the internal application in an automated fashion several times faster than a manual tester now here we've got this opinionated developer John Smith and he believes writing all these tests is time consuming because not only do we have to write the application code which we refer to as production code but we also have to write the test code so implementing a new feature with tests will take significantly more time as opposed to implementing it without tests because a part of our development time is spent on writing and maintaining these tests so this is what John Smith argues but you see really right or wrong well let's see let's say we don't have any automated tests as we add new features and our application grows in complexity the time required to test all the application functions with various arguments increases exponentially if you have worked in a larger application with a lot of features that have been built over years you know that sometimes no one in the team knows how these functions work and how they should be tested nobody knows the requirements because those developers were initially built those features are no longer part of the company so there are a lot of legacy functions around and nobody dares to touch them now if you implement automated testing we can test a large part of applications functionality giving automated tests and the time required to do manual testing will be far less in fact some companies do not have any manual testing at all they automate everything now whether that's a good practice or not it's debatable but irrespective of that some level of automated testing can definitely reduce the manual testing effort but there is also one more benefit to automated testing with automated tests you can catch the effect before releasing your software and this can save you from a lot of nightmare have you ever been in this situation where you deployed the application to the production you were happy you went home and then 30 minutes later you got a call from your boss saying that the critical function in that application is not working and then you have to log in remotely or go back to the office and spend several hours till very late at night trying to fix the bug most if not all developers have that kind of experience at some point in their career now with automated test you catch more bugs before releasing your application into production now I just want to clarify something here I'm not saying that with automated tests you're going to release bug-free code that's not true but what you release is often software of better quality now as you talk to various developers about automated testing you come across two extreme view points on one side of the spectrum we have developers like our John Smith put things automatic testing is useless on the other side of the spectrum we have this guy who thinks you're not a coder if you don't write tests what I want you to do is ignore both these extreme viewpoints instead take the middle ground and be pragmatic the reality is even though automatic testing has a lot of benefits it doesn't fit every project and every team for the starter your team needs to have a discipline in writing clean tests and maintaining them if you don't work in a team like that writing automated tests ends up costing you more than the value you get out of them because you will spend a lot of time fixing broken tests that are hard to read and hard to understand in those cases it's better not to write tests at all another factor is the time and budget of your project let's say you're part of a startup company and you have three months to turn a concept into real working software in this situation I argue that you should not spend your time writing tests initially because you don't know if the fabrication or this business is going to succeed most startup companies have a small budget and they want to produce something quickly so they can show it to a mass audience and then attract venture capitalists to raise funds if you want to spend three months writing tests chances are your application may not even make it to the production so what's the point of writing all these tests plus in a lot of startup companies the requirements change frequently if you spend a lot of time writing tests a lot of these tests break as you modify the application code to implement the new requirements so in those projects it's better to write tests only for parts of the application that would take more time to test manually so use it as a practice to help you increase your productivity and go faster as opposed to hard and fast rules that you need to apply everywhere remember the real world is different from books and courses in the real world we have constraints and most of the time these constraints are money and time you cannot code forever you cannot code for fun your job is to build real working software and solve a problem your job is to deliver value to the world if you cannot deliver working software in time within the budget nobody cares about all your fancy automated tests so once again I want you to be pragmatic and use automatic testing when it makes sense even if you cannot practice automatic testing in your current project or team I strongly recommend you to watch the section thoroughly and learn automated testing because it will help you become a better developer it will enforce you to write better and more reliable code all right ma Sh I got it now tell me how should I write tests well that's the topic for this section so next let's take a look at the different types of tests alright now let's take a look at the different types of tests so in general we have three types of tests unit tests integration tests and end-to-end tests with unit tests we test a component in isolation without external resources like file system database HCM points and so on now this is the classic definition of unit test irrespective of angular in angular terms that means testing a component in isolation without this template and any other resources that touch the file system the database API endpoint the browser and so on so if our component is using a service to talk to an API endpoint you're going to give it a fake instance of that service we assume that service is doing its job properly and we just want to focus and the functionality of the component or similarly if the component is using a router again we're going to give it a fake router not a real router that works with the browser API to take the user to a different page unit tests are easiest to write there are superfast but they don't give us much confidence about the functionality of our application so let's take a look at an example here we have this simple boat component that you saw in my beginners angular course now I've simplified the code here but basically we have this property total votes and this method that would change the value of this property now we can test this component in isolation so we think of it as a plain type script class not an angular component so we don't care that it has a template we just look at it as a simple type script class so this method is responsible for changing the state of this class so we can call this method in our tests and then inspect the value of the total votes property if it's updated properly that means this method is working so writing this test is very easy as you will see later in this section however if there is a problem in the bindings in the template for this component we will not know until run time for example if you forget to bind the click event of this button to the upload method our component is not going to function properly and that's when we use an integration test with an integration test we test the component with external resources once again this is the classic definition of integration test in the angular world that means testing a component along with this template so instead of looking at this class as a plain type script class we need to look at it as an angular component and that means we need to run our test in an angular environment so we need to instruct angular to compile this class along with this template as you might guess this kind of test requires a little bit more code than a simple unit test there is some setup code because we have to put this class in an angular environment we need to deal with modules dependency injection and so on however we get more confidence about the functionality of our components so this is the integration test now if our component is using a service to talk to an API endpoint again similar to our unit tests you want to give it a fake implementation now in some ways this looks a little bit like unit tests and some developers can argue that this is actually kind of unit test because we're still testing this component in isolation without a real service or a real router however I still see this in the category of integration test because our test involves testing a couple of pieces together a component and it's template which is often in a separate file so that's why I personally see this kind of test as an integration test because we're testing the integration of our component class it is template now you made the second with me and still think of this as a unit test that's perfectly fine but let's not get hung up on the terminology but for the rest of the course I'm going to refer to the test that involves the integration of a component and is template as integration tests and tests that work with a component in isolation without this template as unit test now we can write f integration tests for this component and all these tests may pass however when you run the application and use it like an end user the application may still not work as we expect because we're still looking at individual components not the entire application as a whole so let's let me use end-to-end tests so with end-to-end tests we test the interpretation as a whole so we simulate a real user we launch the application in the browser perhaps we log in put in the user and password click here and then navigate to the target page click on this upload button and then ensure that the total votes is updated in our HTML page properly now with this kind of test we get a lot more confidence about the functionality of our application however these tests are very slow because each test is going to launch the application in the browser navigate to the home page then perhaps do a few clicks here and there to get to a target page and do something so that's why these tests are slow but they're also very fragile if simple change in our HTML markup can easily break these tests even if the application is working properly so ideally you want to spend most of our time writing unit and integration tests and write very few end-to-end tests only for the key functions of the application but you're not going to test all the edge cases with end-to-end tests like something they know something being out of range and so on we use unit tests for those scenarios so here are the three main types of text now if I told you unit tests are easier to write so in this section we're going to focus entirely on unit tests and then I will cover integration tests in the next section all right next we're going to look at the fundamentals of unit testing alright now let's take a look at the fundamentals of unit testing the first thing you need to know is that tests are first-class citizens so all the practices you have learned about writing clean and maintainable code applies to your tests as well so here are some examples your functions or methods should be a small preferably less than ten lines of code you should have proper names and they should have a single responsibility the same principle applies to your test code so each test should be less than ten lines of code you should have a proper name that perfectly describes what it's doing and you should have a single responsibility you should test only one thing all right now download the zip file I have attached to this lecture there you'll find this new angular project in this project we have these folders where I have included some code that we're going to use throughout this section we start with very simple examples and gradually as we go through this section the examples get more and more complex now the first thing you need to do after you download this project is NPM install and then ng test so instead of ng serve we run ng test so this is going to build the application and then it launches karma which is our test Runner all right now back here we want to write our first unit test so in the fundamentals folder here we have this compute function a very simple function if you give it a negative number it returns zero otherwise it increments the number by one you may think this is really so simple and it looks nothing like angular I didn't understand that but bear with me we're going to start with very simple examples and gradually these examples get more complex so if you do have some experience but unit testing feel free to skip the next few lectures depending on your knowledge but if you're an absolute beginner you need to look at all the examples all right now to create a unit test for this function and the same folder we're going to create a new file look at the naming convention compute dot spec dot t-- f so all our test files should have ducks bag TS this is the pattern the Karma or test runner is looking for so any time we find files that match this pattern it looks at the test in this files and runs those tests for us now in the projects that we create with angular CLI we use Jasmine as our testing framework which provides a bunch of functions that we use to write tests the two functions that we use most of the time are described and it we use described to define a suite which is a group of related tests and we have it to define a spec or a test so let's see how we can use this subscribe we give our suite a name which is often the name of the system under test so here we're writing tests for the compute function I'm going to call the suite compute now the second argument here is a function that our test Runner is going to call so we can use this function syntax like this or we can use the arrow function syntax which is shorter and cleaner so like this now here we have one or more tests or specs so define a test or a spec we call the ate function and similarly we give it a name test name and a function so this is the body of our test this is what we're going to write and our test Runner is going to call this function and then it will tell us if the test succeeds or not now which is we call this test test main is a very bad name it doesn't tell me what we're going to test here but look at the implementation of this function when writing tests here we need to test all execution paths so here we have two execution paths one is for a negative number and the other is for a positive number so we need to write two tests here so I'm going to change this to should return zero if input is negative now you can read this as a speck of the compute function it should return zero if input is negative alright let's test this so first I'm going to import this function from the top now here I'm going to call it with negative one get the result now we need to assert that this result is zero to do that we use the expect function that comes with jasmine so we expect this result to be zero this is the API that comes with jasmine now we have a bunch of other methods here let me show you so we have to be defined to be false e to be greater than to be less than and so on so depending on what you're going to expect you can call one of these methods you're going to see more examples throughout this section all right now let's run this test so save now because karma is watching our test and source files and soon as it detects a change it runs the test again so here you can see it executed our test and the result was successful now if you have a big monitor you can put this terminal window on the side and as you're coding and saving files you can see if all tests are passing or something is failing alternatively if you have double monitors you can dedicate one monitor purity to your test it's much easier now if you don't like this terminal window you can see the report of your tests in the browser so when you run ng test this will launch a browser window connected to karma now here if you click this T button and open Chrome developer tools on the console tab you can see the list of all tests and their status so here we have one test compute should return zero if input is negative and you can see that this test is successful now let me show you what happens when it tests fails so back to our test code I'm going to change this and say it should be one save now in the terminal you can see we have one failed test and if you get back here and refresh this tab look our test failed expected zero to be one now if we click this line here this takes us to the failed test so here's the line where our expectation failed now like here let's fix this test now we need to write the second test so I'm going to select this test here hold down shift alt and the down arrow to duplicate the code modify the test name should increment the input if it is positive now I'm going to give it a positive number like 1 and we expect the result to be to save back here refresh beautiful we have two passing tests next we're going to look at testing strings and arrays all right now let's see how we can test strings and arrays so in the second folder arrays on strings let's take a look and this grade function so a very simple function we give it a name and it returns welcome plus that name so once again I'm going to create a new file greet let's pack the TS and to save time I'm going to copy a describe block here now what are we going to test here well what I am sure that the name that we give to this function is in the output so it should include the name in the message or the output once again I'm going to port the function on the top okay now that here call greet has much to it and then we expect the result to be welcome wash now there is a problem with this test this test is too specific so if one day I come back here and I decide to add an exclamation mark here this test is going to break we don't want fragile tests that break often so instead of checking for the exact message I'm going to check for the existence of my name in the output so I'm going to replace this with to contain wash now this test is a little bit more general and if I change the message from welcome to hi in the future this test will still pass the same principle applies when testing arrays let's take a look at another example so here we have gate currencies that returns an array of three strings if I want to write two tests for this function I just want to assert that the result includes these items u.s. dollars Australian dollars and Euro but I don't care about their exact position because if in the future I decide to change the order of these items in this array and sort them alphabetically I don't want my test to break so once again get currencies that's back 30s now once again I'm going to paid some code but from the next lecture you're going to have you spec files ready for you so you don't have to type it from scratch here is our test suite now let's write the test it should return the supported currencies I'm going to import the function on the top and then call it here get currencies store the result here now I'm going to expect this result to contain US dollars duplicate Australian dollar and Europe their order does not matter alright from the next lecture you're going to start testing angular components now from this lecture we're going to start testing angular components in each lecture you're going to see a pattern that you see in a lot of real-world applications so let's start with the first pattern in the folder called setup and teardown open this both components so this is a simplified version of the both component that you have seen in my beginners angular course you have a property total votes and methods that modify the value of this property the pattern we have here is state change so in a lot of components we have methods that modify the state of the component now in a real world scenario chances are after modifying the state here you may use a service to make an API call to save the changes on the server that's a different pattern and we're going to get that later in this section so for now let's just focus on the state change pattern now back here we have a spec file here we have some boilerplate code so you're gonna have to write everything from scratch note that the name of our suite is both components that's the system under test now let's write a couple of specs so this both component should increment total loads when uploaded so here I'm going to create an instance of the both component call the upload method expect that component the total votes to be won this is how we test this method now these three lines you see here represent a structure that you see in a lot of unit tests we call this structure Triple A which stands for arrange act and assert so the first line here is their range part where we initialize the system under test in this case we're creating an instance of the gold component the second part is the Act which often involves calling a method or function and the third part is the assertion best practice to make your tests clean and readable always put a vertical line between these lines like this all right now let's write the second test so I'm going to simply select this duplicate you don't need this one here all right now let's change the name of the test so should Dickerman total votes when downloaded I'm going to change the call to download method and then total votes should be minus one now look at these two tests these two tests have something in common the initialization of our both components now this initialization is only one line of code and it's not a big deal but sometimes when working with more complex objects the initialization may involve few lines of code we can refactor these tests and move this initialization to a single place so we're not duplicating it in each test so I'm going to cut this line here and move it inside the body of our sweet delete and delete now each set is only two lines of code however there is a problem with this test if you run this says the second one is going to fail because in the first one we're uploading so the value of total votes is going to be one and this means in the second test the value of total votes is going to be zero not negative one so the problem we have here is that our tests have side effects the execution of one test can impact the execution of other tests and with this our test will break quite often which is really painful we don't want fragile tests remember how can we solve this problem well when writing automated tests remember each test should run in an isolated work as if it's the only test that exists in the world nothing else so we're going to start with a clean state how can we do that now previously we didn't have this problem because we created this component inside each test but now that we move this line inside the body of our suite you have this problem the solution is to use before each function so in Jasmine we have another function called before each as the argument we pass a function here and our test Runner is going to call this function before each test and this is a perfect opportunity for us to initialize our objects so I'm going to change this so the type of components both components so we'll have intelligence throughout this module and then do the actual initialization here now in Jasmine we have three other functions that are similar to before each we also have after each the same signature so it takes a function that will be called after each test and this is a place where you do clean up now in this case we don't need to do any cleanup but in your test if you need to do clean up after your test this is where you add your clean up code we have two other similar functions before all which is executed once before all tests and after all which is executed once after all tests so in automated testing terms we refer to what we write in the before each function as the setup and what we write in the after each function as the turndown these are the terms that you hear in a lot of unit testing frameworks irrespective of the language next we're going to take a look at an example of a form hey thank you for watching my youtube video my name is Mohammad Ani and I'm a full-stack developer applause I'd author and in getting the instructor with about 14 courses at the time of recording this video so I've got lots of courses on both front end and back end development including c-sharp energy framework a statment MVC angular architecture in it testing and so on this video watch is actually part of my angular course on udemy that you can get with its discount using the link in the video description and if you want to see my other courses simply head over to program with watch comm slash courses you can also subscribe to my youtube channel get free videos every week have a great day and also back show [Music]
Info
Channel: Programming with Mosh
Views: 259,007
Rating: 4.8378887 out of 5
Keywords: angular, angularjs, angular.js, angular2, angular 2, unit testing, automated testing, jasmine, karma, programming with mosh, code with mosh, angular 4, angular tutorial, angular testing, unit test, angular cli
Id: yG4FH60fhUE
Channel Id: undefined
Length: 32min 34sec (1954 seconds)
Published: Thu Feb 02 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.