Techniques and practices for testing Angular - Duncan Hunter & Adam Stephensen

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone and welcome to technics and sorry for techniques and practices for testing angular I'm Adam Stephenson I'm a solution architect at SSW I specialize in building large enterprise web applications and I'm lucky I've been building angular and not dotnet core applications since they're both in early beta in Brisbane and been really lucky over the last couple of years to just pretty much only do the new angular stuff and I spend about half my time writing code for clients and traveling and the other half of my time traveling around talking about it and teaching which is really fun because that's where you really learn because you get to see what everyone else is doing so hopefully we can share some of that experience with you today around testing so you're going to hear us say angular 2 but what we really mean to say is just angular because the angular team would like it if everyone stops using the version numbers in the naming because it's been quite confusing and we're currently at angular 4 and soon we're going to be probably next month we might be at angular 5 so the idea is that it's going to be evergreen a bit kind of like Chrome I think we're at sixty because I think I'm getting some touch bar features for my macbook for Chrome in version 60 I'm not sure yet but just like chrome you don't really know the number angular is going to be the same so if you're talking about angular the first version you should be saying angularjs and if you're talking about the second version or four or five or whatever comes after that then it's just angular so you'll see us try our best just to say angular so who here in the room hands nice and high is tested angularjs okay cool probably close to half the room that's good and who has done any testing with the new angular okay so if you have hands and so probably a third of the room so you're all in the right place we're gonna be talking about all the new stuff that's in the new testing utilities for angular so in 1979 was the first time that debug that testing was actually differentiated as a different practice to debugging in 1996 we got XP and which had a real focus on testing in 1998 we got s unit F by Kent Beck which was the unit testing framework for small talk which is the first of the xunit frameworks which is you know really what a lot of our current testing is still based upon in 2001 we got jeaious unit from pivotal labs and there's worth taking a note of them they pop up a fair bit and that was the JavaScript implementation of s unit we got 2,000 in 2003 we got TDD and in 2006 we got behavior driven design by day and North was like an extension of TDD with human readable tests and in 2006 we got selenium for doing outrunning out in doing tests and in 2010 we got Jasmine from pivotal labs again which was the updated version of jeaious unit in 2010 we got angular 1 which is the first time I had a framework or in the yeah was the first time that we had a framework where the hello world was actually unit tested which I was really excited about because from the very first day angular 1 had a real focus on testing which was excellent we got 20 in 2011 we got karma from Google whose original name was testacular and I really wish they'd have stuck with that because I think that's pretty cool in 2013 we got protractor for running our angular end-to-end tests which uses selenium under the covers and in 2016 we've got angular 2 now I find the history of testing really interesting because when you look back over it we're using protractor which uses selenium under the covers we're still running our unit tests in karma we're still writing them in Jasmine Jasmine uses BDD we're still encouraging TDD like the tools that we're using in the practices that we're using they're not new and this is by far the best coverage of we seen in any room of testing and we asked exactly the same question in January this year in London and two people had done angular 1 testing and no one had done any angular 2 testing and so fought so it's always been a struggle to get people to do testing and I think that's because it's traditionally been hard and front-end testing has been harder than back in testing and that's we're here to talk about today is we think that angular's made it a lot easier the the tools and the frameworks that angular has given us have made front int us testing much more easy and that's all we're gonna cover today so the agenda we're going to talk about the tools that we've got for testing we're gonna have a look at jasmine we're gonna talk about faking dependencies we're gonna look at the testbed API and we're gonna talk around the challenges around testing asynchronous code with the async and fake async methods and then we can look at into in tests so let's jump in and talk about some of the common tools that people use for testing with angular but it's important to remember like Adam said that testing is not an afterthought for angular you know it's it's been baked into the system from the ground up and so much so if you go actually go to print out the documentation on angular do it's 99 pages long so it's actually a fair bit and that's just how to kind of use it not sort of best practices as well and that's I only know that because Adam actually likes to print out documentation and read it which is kind of strange bit so it's a there's a lot of information around and there's two main types of tests that people do with their angular code the first is unit tests where you're just testing a small function or a small piece of section of your application and then you've got into n tests which are completely different where you actually run the entire application in the browser and then you query the Dom in the browser and select elements and run tests against what they've got the tools at the moment that are the most popular is karma as a test Runner and then using jasmine as the testing framework for the syntax and the assertions and all of the matches and all of the different spying and faking utilities that you get but angular is also a big part of those testing utilities especially in the next version of it the very angular 2 or 4 or 5 and there's lots of different testing helpers we're going to go through when you're doing it into n tests then you've got protractor is the main tool for running it into n tests but a lot of people are using jasmine as their testing framework on top of that so the syntax is very familiar across the to there's other ones you can use if you are used to using say mocker and sign-on you could do that and more frequently I've seen people wanting to use jest and I've really enjoyed using just for running tests because they're much much faster and also running an ode you don't have to worry and you see I process about having chrome setup and other sorts of things but that's still you're still way out on the fringes if you're using just with your angular by far and away it's almost like 99% of people using jasmine and karma and everyone's using angular utilities so what does Jasmine look like well if you look at an individual JavaScript test they very often look like this where you'd have an it or a single speck or a test that some of the words you'll hear and they will take two arguments in the function the first is a string which just describes the individual tests and then it takes a function as the second argument where you actually do your tests and you can see here we have a Jasmine matcher with the dot two equal but there's a whole bunch of other kind of helping matches from the Jasmine library or oh yeah library and then you would normally wrap this test in a describe block which is where you'd have a suite of tests so inside this describe block which also takes two arguments of a string describing the set of tests and the actual function that is where you put all your tests so you might end up having a couple of tests inside these describe blocks and you often end up nesting more described blocks inside of this described block so if you were testing say a logout function you might have another described block just for that logout function because you'll have four tests around that one particular function so it ends up being a nested structure but that's the kind of the basics so comas a test runner that runs in the terminal and you can run it on your CI processes and you'll get this output like this in the terminal we'll say it's executed say for example six of six tests and most people tend to run this on another screen just so they can have some room and then you've got protractor and that's very similar but the way that it actually runs your test is fundamentally different and we'll be running some of these tests today so here you can see it's running in the terminal and it's showing kind of that behavior driven development kind of wording there so the the describe blockers page colon joke page and then the next part of it down here is the individual tests running so one of my other favorite testing tools is Duncan is such a fanboy of wallaby that he actually got them to make stickers wallaby stickers in the world I actually have a whole bunch of them here if anybody wants a wallaby sticker later they can come get one but what the it who's used wallaby who's heard of wallaby oh yes so it's getting more popular so it's a hundred bucks I'll just get that out there every year you've got to be into it but it's great if you're riding lots of tests or there you really value testing and then it can be worth it so this is what it gives you on the left-hand side of these tests here you can see you've got a couple of green and red dots so the red ones failing over here and then on the other side you can see that it is expected to be three so what you'd get in the terminal you get right here there's a bunch of other benefits you get a lot of test coverage tools and other sorts of things but that's kind of the real big bonus of using it angular CLI is also a really important testing tool because it comes with all the live they're testing harness setup so rather than having to go set up all of these tools and get them to work together you can just turn on the CLI and run so it's a great way to learn to test but it's also great for client projects and real projects and we we pretty much run the CLR and everything we do so in summary for the tools we think the CLI is awesome and that you should be using it for most projects and that karma and protractor and Jasmine really are the default for the community at the moment and that you should check out wallaby jeaious that's pretty cool and can help out and we'll be using it a bunch today so you'll get to see it so let's move on to talk about jasmine for a second and let's jump in and actually write some tests so we've got this very simple application we're gonna write some tests around today it's a Chuck Norris jokes application and you can click the button that shows the next joke and the reason I like this for showing testing is because it's it's ink insanely simple to understand what it's doing it's just a component and you've got some button clicks which talk to a component that talked to an angular service that talked to a back-end and then you've got to think about how do you deal with all of those dependencies and fake out the things that you want to fake out and all talk about your choices of how you do that so it's very simple to understand but we'll talk about the different practices you can use okay so let's jump over into the idea and let's actually run a couple of tests if I come over into Visual Studio code here you can see that we have a very vanilla angular CLI project that we've used to make it and if we open up the source folder we have this app folder and inside of here we have a joke feature and this joke feature just has a joke component TS file a joke service and it has a spec file and we'll show you more of the joke component but I'm just going to write some of the simplest test we can in angular for now so if we open up this dot spec dot CSV file and the build tool is looking for anything that ends in dot spec TS so that's how it knows to run Carmen knows to run these files when you ask to run your unit tests so if I give us a bit more room here I'm going to come in and write a describe block and I'm going to say that we're going to be testing a suite of tests here so the name I'm going to give we're going to be testing a component here and we're going to be testing the joke component and then down in here I can do an individual it block and or just a test and I'm going to start off with something very simple and say that it should add one plus one here and then down in here I can do a Jasmine expectation and I can say that I expect one plus one equal three so of course this is going to fail and I can open up the terminal at the bottom and I can run ng to get a hold of the angular CLI and then just run test and it's going to kick off karma and Karma's going to build our app and run our tests so in this case we expect it to fail and sometimes I don't mind these sort of sanity tests in my application because when you've got lots of dependencies to configure and lots of services to fake and other sorts of things sometimes a simple test like this can be nice just to see that it's running and you've got all your dependencies lined up so down here you can see that it executed one of one tests and it failed this is your default experience with the CLI and it expected to to equal three so I could come up here and fix this and then it will just rerun because it's comments watching by default it'll watch the file save because I'm automatically saving in Visual Studio code and then it's saying one of one successful so I'm gonna kill this now kill the terminal and I'm just going to push command shift equals to open the Wallaby shortcuts and then push start so now we'll just run the rest of the demo with wallaby but pretty much it's doing the same thing it's just running your tests but it gives you a feedback right now and in the IDE straightaway and you can get it for like visual studio and web pack and a bunch of not web pack crossing over here a web storm there's a whole bunch of different ideas that works for so if I change this to be equal to three you'll see will fail and show you the thing there and then if I change it back it'll rerun and it's quite fast it's usually faster than your experience with running Jazmin and karma but it feels a little bit as fast as Jess which is super fast so I'm going to come down and write the world's simplest angular test now so I'm going to do another it block here I'm going to say that it should have a title of let's say Chuck Norris jokes here Chuck Norris jokes and just going to copy this so we can test against it so down in here I'm going to have a constant here for our component component and this is going to be equal to a new joke component and this joke component has a dependency on the joke service so I'm going to get this red squiggly here because it's saying oh you got to pass in something for this dependency in the constructor of the joke service we need to talk a whole bunch about this but for now I'm just going to shortcut it and pass in null so I just want to write a really simple test I'm just going to test the title on the page or actually the title of the property in the class of the component nothing to do with the HTML template yet so in here then I can do another Jasmine expectation I'm just going to say that I expect my component title and I really love this every day I still get off on it because we got typescript in our unit tests which is great compared to what we used to be doing so I get all this good intellisense so I expect my component title is going to be equal to the string of Chuck Norris jokes and it looks like wallabies frozen up I'm just going to restart that and rerun it so then you can see down here it's passing it's showing me at ran it in two milliseconds but if I make this fail here we can see that it it's failing and showing us the message on the side here so that's go to the simplest way you can run an angular test and I still really like that if I don't have to deal with the HTML and I've just got a really simple service but you'll see us get into more complicated tests now as we move forward so we had a quick look at how we can just use the syntax here and we had a look at how we can just new up a component or service but we'll talk more about other ways to make your dependencies for your tests so in summary jasmine really is the default still for the angular community in terms of your testing framework and it's more than syntax so you know there's a lot of helping functions and fakes and spies and sorts of things like that which we'll show you now awesome can I just get can I switch over from the hand hill to this one because I'm as I'm coding the hint this one's going to be much easier if that's okay awesome excellent okay so we're going to talk about faking dependency so the faking and setup of dependencies is still one of the hardest parts of testing so it doesn't matter what testing you've been doing what whether it's back in testing or front-end testing if you're trying to test a unit of code and that code has a lot of dependencies managing the those dependencies and testing around those dependencies is one of the greatest challenges and we have that a lot when we're testing our our angular applications so we're always injecting services so this is how this is the code that Duncan had we had were instantiating a joke component he was just passing in null but to be able to do any real kind of tests we need to be able to work with that service so what's a very common pattern is that we'd go and create a fake object we'd create our own object we'd put a function onto that object and it would return something that we knew so that then when we're asserting against our component against its behavior when we can expect what that dependencies behavior is going to be so we then we take that fake that we created and we pass it into our service and we can run our tests an alternative method to creating your own fakes is to use Jasmine spies so what we can do with the Jasmine spy is that we can take an object pass it in and then we can put behavior or override behavior on that object so in this case we're taking a joke service and we're saying let's get the get joke method and let's attribute this particular behavior so it's going to return a value and the value it's going to return is an observable to fake joke now why spies are great is they let you intercept any function call so you can use your real service and intercept the function calls and you can override the behavior of that function what's really great about spies is they also let you check the interaction between your class or your component and the dependencies so we can check to see whether the joke service whether that joke method was actually called we can check how many times it was called and we can even check what parameters were actually pass to that get joke method let's go and have a look at what that might look like in code so I'm gonna create a new test and the test that I'm going to create is it should set the joke property when initialized so let's go and just jump in and have a bit of our look at our joint component so when our joke component is initialized mg on in it executes and we execute the get joke method the get joke method calls our joke service cause it's Jack get joke method and it takes the observable that it returns and then map's it into this joke property on our component so what I want to do is I want to check when the components initialized this joke gets set the joke property gets set so I could come down here and I could come in and like Duncan's done I could just come and instantiate a new component but what I'm gonna do is I'm gonna lean on jasmine a little bit and I'm gonna use its before each functionality so that I don't have to in every single test actually have to instantiate a new component so I'm going to come up here and create declare my component at the component and I'm gonna say it's gonna be a whoops joke component and then I'm going to use our before each to say when I come in say that my component is equal to a new joke component and just like Duncan did for the moment I'm gonna pass him null and now because I've done that I can come and remove the instantiation of my component from out of the test and Duncan's test will still pass okay so I don't need to do that now down in my test so our test we're looking to set the joke property when it's initialized so I want to come in here and I on my component I want to call the ng on method which is what happens when it's initialized and then I want to do an assertion and I'm going to expect that the components joke property is equal to something that I know so fake something okay now how am I going to do that I'm going to inject a dependency into my joke component for my service so I'm going to come up and I'm going to create a fake joke service fake joke service and I'm going to say just my fake joke service can be in any so now in Y before reach I'm going to say that my thanked joke service is an object and on my object I'm going to come in here and I'm going to put a get joke method on it and what I'm going to do is I'm going to say it returns an observable of fake joke now I don't know I do I need to come up here and import of I'm just because it's a test I'm going to import the rxjs kitchen-sink obviously wouldn't do that oops in my actual application so now I've got the off keyword and now what I've done now that I've got this service I can inject it into my component and I know what that service is going to do what I call the get joke method so I can come down here I can see that Wallabies already telling me that it's going to work because now I can check and I can say like my joke the the joke on the component I'm going to expect to be what I passed into it so that's using a fake object I could come in here and instead of doing that what I'm gonna do is use a Jasmine spy so instead of creating my own object I'm going to come in here and say that the fake joke service is equal to jasmine dot create spy object and I'm gonna pass in my fake joke service and then I'm gonna pass in an array and that array is the is the methods that I want to specify on that fake joke service I'm gonna pass then get joke and now I can attribute the behavior that I want on to that get joke method so I can come in and go fake joke service get joke and tell it what I want to do I want to return a value and the value that I want to return is an observable of fake joke and if everything lines up my test is passing again so there's two ways of doing the same thing I created an object and passed in a fake object and then I created a Jasmin spy now what's nice about the Jasmin spy is I can come down here and remember I can I can check how my component is interacting with that service so I can come down here and I can say expect that my fake joke services get joke method has been called okay so it so I can now check that interaction of my component under test with its dependency so if I don't cut if I don't call the method by not calling on in it it's going to give me an error I can even come down here and check how many times it's been called so was it called three times No was it only called one time oops yes pretty cool so we're getting a lot of extra power out of using Jasmine spies so we had a look at injecting a fake object and then we had a look at the benefits of using Jasmine spies so the nice thing about faking is they're isolated I'm actually going and creating an object that just has the behavior that I need there's a few downsides you can end up with a lot of duplicated code and you can up and end up in the situation where someone goes and updates the behavior of the service and they don't update the testing the tests around it so you can end up shipping something into production where all of the testing is working but it's actually not running in production because the tests haven't been updated the benefits of spying is that you've got the spying functionality and assertions and you end up with cleaner code so it's important to know that I've given you two strategies and two different tools and you need to have both of them on your tool belt both of them you'll need in different circumstances and the faking and setting up of dependencies is still one of the hardest parts of unit testing which is convenient cuz that's where we're up to so let's talk about the testbed API because that's one of the newer parts in angular at the moment so we're gonna talk about a few different types of tests now because the test beds help us solve a different type of test so we've been writing these isolated tests were just testing the properties and the methods on a class or it could be a component or a service and we have no HTML template involved whereas in the community there's this concept now people talking about shallow tests where you're testing not only the components class but also interacting with the HTML template that's involved and being able to select the HTML template query say an element on there and check its value then run detect changes and do some work with the test and then see if things have changed there's also integrated tests where you're testing more of the app more components at once or the entire application but we're just going to look at isolated and shallow tests today so we're going to use this testbed the main thing you're gonna use it for is configuring your tests so you can come in and say testbed configure testing module and being a hint in the name there it sets up a module for you and if you've done any angular it's just like an angular module and you can pass in all the parts of what a normal angular module need and being an angular module what it does is it says for this section of my code these are all the dependencies for it to be able to run so for this set of tests these are all the dependencies for this set of tests to run and it's one of the pains in the butt of doing front-end testing and setting up all your dependencies so this can really help so the first thing we have here is imports and that is all of the other modules you depend on so we have HTTP dependency in our joke service so I'm just bringing an HTTP module I have declarations and that just another fancy word for components so we have the joke component which is what we're testing and then we have providers and that's where you register your services your angular services so we're registering our joke service here so once we have this testbed it gives us a hold of this fixture and that's kind of the second main reason you want to use test that is to be able to get a hold of HTML templates not just because it's super easy to set up dependencies so you also you can use the testbed to set up your dependencies for a service which has no template but this testbed create component and then passing in the Joe component gives us this fixture once we have this fixture we can get the component itself again which means we've got the properties and methods accessible but we can get this debug element and it's this fixture debug element we can use to query the HTML template associated with the tests and we can do a bunch of other things like run fixture dot detect changes so that after you do some things in your test it will then go and update the change detection so the things are bound to the page again that you've done in your tests so we can say fixture dot debug element query and we can query by CSS so any CSS selectors you used to using you can use them here to be able to query the Dom to grab whatever you want so in this example I'm grabbing the paragraph element and I can call dot native element if I'm running in a browser environment to be able to interact with that P tag as if I am in the browser so this is going to give me all the browser specific API this area for this P tag so the test but it's really great because it can it can really help make a testing module and give you this kind of system for building up all your dependencies for your tests because it gets much more complicated than this when you have six dependencies or six services and two or three components and a button and the router and HTTP and all sorts of things you can query the HTML templates with it you can run detect changes and you can do a whole bunch more so it tends to be the go-to for most of your tests but if I can I still like to just and you up the class if it's if it's something simple so let's jump over and actually configure our current tests to use the testbed and run a test against the HTML template and do a couple of different tests in that way so I'm going to jump back over and I'm going to take a little bit of pleasure in getting rid of Adams tests maybe I'm enhancing them okay so we're gonna say that we want to have this fixture property but we're going to initialize it down below so I'm going to say let fixture of type component fixture and the type of component fixture is going to be the joke component and then underneath here we're going to need to get a handle on the component as well and this is going to be of type joke component and then we're also going to get a handle on the the almost did company there and joke service here so we want a property for the joke service and that's going to be of type joke service so if you've done much testing you probably going war wait a second you're passing in the real service here this is a decision point for all of your teams how value do you want to get out of your front-end testing so I'm gonna pass in the real service here but make sure that I'm going to intercept it and I never actually call the real back-end that the service can and if I had more time that I would also fake out the HTTP section so I really can't stuff up and call the backend but for now we're just going to intercept all requests out to this service with the spy but I like this because one it's easier to configure but two it's giving me a little bit of more and this is my personal opinion it's not black and white and it's not right and wrong because then if someone changes this joke services methods and properties now my tests will break as well because I'm actually interacting against the real joke service so this is definitely something your team is going to need to decide on what flavor do you like to do do you want to test more of it and get a bit more kind of integration sort of testing in a unit test but for now that's what we're going to do so I'm going to come down here and I'm going to get the test bed and I can call configure testing module on it and that takes in an object and the first thing we're going to do is imports which is an array and we're going to pass in the HTTP module and then we will get declarations and that is also an array and we only have joke component in this example and then we have our providers so you saw this before and this is going to be the joke service that we want to register with angular inside of these providers so once I have this I can use this test bed to initialize all those properties above so I want to get this fixture because I want to interact with the HTML template so I'm going to say fixture is going to be equal to the test bed create a component for me in the component I want you to make please test bed is this joke component and with that I can start using this fixture for lots of things so next up I want to get the component and I'm going to initialize that with this fixture and I'm going to say hey fixture can you please give me a handle on the component instance and then also I'm going to use this test bed to get a hold of some dependency injection so this is a different way to doing dependency injection in angular than you are angular than before so I can say that I have this joke service and it's going to be equal to the test bed dot get and there's a whole bunch of different helpers on this test bed this is just one of them and I want to get an instance of the joke service so I'm going to ask it to inject that joke service so it's available in my test but now I've actually got the real service so I've got to be careful with what I do here and I've deleted Adams service I'm also going to delete his test here just for fun and I'm gonna come in here and make another test so I'm going to say in this one not now I'm not saying we should initialize the property we should have the HTML template with the text actually on that template so in here as they should have a joke bound [Music] bound to the template so inside of here I'm going to need to show you another way that you can use a spy same exact same thing just a different syntax so I'm going to spy on here the company service so sorry joke service I can hear some people helping me out here we just ran a 2-day workshop where everything was about companies so I apologize so just switching entities in my brain so joke service here and I want to spy on the get joke method and then I can go down here and say and dot and we'll see all the different things that are available on a spy so I could call a fake or call through but in this case I want to return a single value so what I want to return here is going to be an observable dot of the string of the joke so for now let's just say something that's not looking like a joke like fake joke and then underneath here what's happened is we've just instantiated this joke component and we've gone and make this request and the spies intercepted and given back this fake joke but that's changes so we have to actually run detect fixture dot detects changes here so the HTML template will update so I'm going to come in here and use this fixture again and say here that I want to save fixture detect changes and execute that so now the HTML template will be updated with that fake joke string and then down in here I can set up a constant joke paragraph element and it's this joke paragraph element I'm going to use from the actual HTML so here I can say fixture oops fixture the debug element query and I am query by dot CSS and the CSS I'm going to query by is this P tag and then I want to get ahold of the native element of that so I'm going to need to import by from platform - browser so this is the browser based thing and then down underneath here I'm going to do a Jasmine expectation I'm going to expect that my joke paragraph dot text content content is going to be equal to the string of fake jokes let's just see if this will fail first done a whole bunch juice I'm actually just going to restart all of you for a second and that should kick back in and say you're expecting fate to equal fake jokes so let's just finish that off and now our tests passing so that's pretty cool we're actually grabbing the HTML template and checking the P tag so of course this is going to be more brittle and now you're more invested in keeping up to date something that's married to the template as well but that's quite powerful so we had a look at how we can set up the test bed in the before each and how it can be much easier to actually set up all your dependencies because when you do a lot of angular you're making modules all the time so it's the way you used to doing it and then we were able to use a debug element to query by that P tag so it's a pretty big API there's lots of things you can do it at this test bed so it takes a bit of time to learn and get comfortable with but it's well worth it use it in all your tests and it helps you make basically an NG module to set up your two dependencies and then it runs everything in a zone and if you're a little bit like me the very first time I heard the word zone I'm like what a zone so I'm gonna pass it over to Adam and he's going to talk about signs awesome so I'm going to talk around the challenge and talk about the challenges around testing asynchronous code because asynchronous code eggs codes complexity to writing your JavaScript unit tests if you've got you know it's quite simple to have a form with a button on it the button calls a service the service makes a HTTP request which would turn something and then when you're doing your tests you want to assert that is all about working together but the challenges around that asynchrony so luckily so how we've been doing that in the past is with jasmine done callbacks and they work by using a promise and then calling done the downside of jasmine done callbacks as they require chaining promises handling errors and then calling done explicitly and while we don't actually really recommend them or like using them that much we still need to use them sometimes around some edge cases what we've got now which makes life a lot more fun is the a is the async method and the fake async and really the key to them is zones does anyone want to try to scribing zones no okay so Zames zones aren't difficult I just think they're a little misunderstood okay so here's the textbook definition is that zones defined and executors define an execution context for asynchronous operations so what happens when you're executing your asynchronous code in angular is it executed within a zone so whenever you kick off an asynchronous operation like a button click what happens is a mod is a micro task is put on a queue when that when that task completes the micro task is taken off the queue and why that's really powerful is angular's aware of when there's outstanding asynchronous operations now when we come to testing it gets even better so we've got the async and the fake async keywords and what happens is when you wrap your tests in the async keyword they're now going to execute inside a inside a testing zone so what happens now is when I do something like do a button click in the testing zone I'm putting a micro task on the queue and I can now use fixture dot when stable to know when all of the micro tasks have taken off the queue and all of the asynchronous operations have completed so it's going to make our testing much easier so when we're writing a fixed it up when stable resolves when all pending asynchronous activities within the test completes so it makes it much easier for testing async in our angular apps now this fake async and fake async is similar to async but we use instead of using when stable we actually use the tick method and tick simulates the passage of time until all of the pending asynchronous requests are complete alternatively you can specify a number of milliseconds to to simulate waiting ok so what's really nice about fake async is instead of using result waiting for when stable it's actually a much more linear progression through your test let's go and have a look at what that might look like now I'm gonna do a test and I what the test I'm going to do is I'm going to say it should get the get the next quote on button click so Duncan's previous test should have a joke the end of the page said when the page is initialized we should go out and get a joke from the service and bind it to the page and check that and that's that was nice but I'm going to take it the next step and I'm gonna say let's do that but when the buttons clicked it should go and get another joke and it should bind that to the page and I want to test that as well now Duncan keeps deleting all my code but I'm more of a copy his code and still it kind of a guy so I'm gonna take the code off his previous test and then I'm gonna go and make it better so what he was doing was he was creating the spy then he was doing a round of change detection he was getting a handle on the joke paragraph and checking the tax I'm now gonna go and get a handle on the button so I'm gonna I'm gonna create the button I'm gonna say fixture debug element and I'm gonna do a query by CSS for a button and then I'm gonna get the native element and what's really cool is I can just go button dot click so I've now simulated close I've now actually clicked the button so what I'm going to do now is I'm going to come in I'm gonna need to do another round of change detection so I'm going to do it detect changes and now I'm going to do my assertion and I'm gonna say that I want my joke paragraphs text content to be equal to something else okay but at the moment my return value is only returning a single value and I'm going to go and query the service twice what's with the page loads and once when I hit the button so I'm gonna change that to return values and then I'm gonna come in here and put another value in what I'd really like to be able to do is come in here and go observable of fake joke too and put a delay on it of say two milliseconds because that would be a cool test to simulate waiting longer on the second one I'm not gonna call it a bug but let's say that there's still some work going on to make that happen for me so what I'm going to do instead is I'm going to come in and I'm gonna do an observable timer and I'm gonna say wait 2,000 milliseconds and then do a map and what I'm gonna do after my map is then I'm going to return fake joke - okay and that'll do the same that'll do the same thing so now the first time I request something from the service it'll return fake joke the second time it's going to wait two seconds and then return fake joke - now you can see here I'm having some issues obviously so the buttons getting clicked I'm doing detect changes and I'm still getting the initial fake joke because it's waiting two seconds to send me the second message does that make sense so what I want to do is I want to take control so I'm gonna wrap the whole test in fake ASIC okay and that's going to give me the ability to actually take a whole word on there I missed it I think you put it on the very bottom closing the hole there we go it looks like the Kampala was just ah no no I've taken it off all you think it's waiting for me I try again the suspense suspense there we go that's better I actually was put in the wrong spot okay awesome so now what I've done is I've wrapped the whole method in fake async and what wrapping the whole method in fake async gives me the ability to do is to come in here and go after I click the button what I want to do is I want to come and wait let's wait those let's wait two seconds and see and I'll need to import tick I'm getting back its now it's so now it's simulate simulating waiting the two seconds and now I'm getting back what I would expect which is fake joke - and my test is passing so the fake async method lets me control simulator time what's really cool is that even though I haven't I'm just going to call out even though I've got a two-second wait it only took 30 seconds - 36 milliseconds to execute the test because fake async is working with simulated time now I'm gonna show you a very similar test I'm gonna do exactly the same thing but I'm going to do it with async instead of fake async so I'm just gonna import async and remember I said instead of using tick a the async users fixtured dot when stable and I do I'm gonna say then and what I'm going to do is I'm going to move my detect changes and my assertion up into when stable extra bracket oh not having luck with brackets now am i there we go okay so and I can't so I'm gonna use when stable now because I'm using an async method instead of tick and you'll see in a second when it reloads that my test is passing okay so it's doing the same thing but now I don't have that linear progression the other interesting thing as you can see my async test is actually using real time so it's actually taking the field two seconds to execute so we had a look at using the async wrapper calling the button click and then using fixture dot when stable to resolve our async tests as well as using fake async and using the tick method the benefit of async is it really does simplify coding our asynchronous tests I prefer fake async a lot of the time because the tests appear to be asynchronous the challenge with fake async though is that there's some situations where it doesn't work for example you can't make xhr requests so in summary testing is still writing testing codes can still be a little edgy and but the new helpers that we've got around with async and fake async make life a lot easier so these bits are cool and we're looking at writing unit tests but let's actually shift gear a little bit now and let's actually write a couple of end-to-end tests to finish up so the intent tests ensure that integrated components function is expected so you've got to take that mind shift of going what I'm really doing here is running the entire up in the browser I could not actually know that it's angular in a way and then I'm selecting things off the page and checking that they're actually what they're meant to be so usually they're very different they run a lot slower usually tend to run them when you're checking in your code or when you're actually writing them you don't let them sit there spinning away like when you're writing you or if you're going to be doing test-driven development sort of thing and usually you're testing more users story where they login navigate to a page click a button so it's a very different motivation for these tests so let's go write some very simple tests around and to enter around the testing the joke title and also around the joke button so it's kind of similar to what we did with our unit tests in a way so if we jump back over to Visual Studio code here I'm going to close this down and just open back up Explorer here and you can see at the very top we have this e to e folder and that was put there by the angular CLI and you get a default test out-of-the-box I renamed it to be jokey - E - spec PS but if we open this up we can see here that it's empty and the very first thing I'm going to need to do is import a couple of helpers here and I'm gonna get these from protractor because that's what we use for writing these tests so I want to get element and so I can select some elements I want to get by so I can actually do that CSS selecting and I also want to get a browser helper so I can navigate around so then I need to make another describe block so you can see what using jasmine again so it feels very familiar so here but my motivation is really different now what I'm actually testing is a page or a set of pages in a lot of cases in this case we're testing the joke page and I like to think about it like a page versus a component because I'll have lots of components on a page normally so in this case down here I can come down and make another individual spec here and I'm going to say that it should have a title of the similar sort of thing here of Chuck Norris jokes and I'm gonna grab that like we did before just so we've got the same thing again so down in here what I'll kick off by saying hey browser can you go get to a URL for me and I just want to go to the base URL for application we actually have no routing because it's a really simple app just go load the page and navigate to here and then what I want to do next is I want to get a hold of our title so I'm going to set a constant of title and this is going to be equal to element by dot CSS and I want to grab the h1 element because that's what we've got our title of our application in and then once I've got a handle on that I'm going to use the text function to be able to actually get the text so you can see the syntax is slightly different here from protractor for the helpers but it feels very very similar then once I have this then I can do a Jasmine expectation again and say that I expect my title to equal the Chuck Norris jokes here and missing the quote on the end there now I don't have any whiz-bang wallaby here to spin this up and run really fast because that's not what end-to-end tests do or how they work I have to actually run this and it fires up the browser so I'm going to give us a bit of room and move this over to come out of full screen and move this over to the side here just get rid of these and if you're very fast like Superman you'll see when I run an NG eatery down here in the terminal you'll see it'll spin up the browser on the side the default is going to be chrome and it's going to navigate to the root of the application and then it's going to query by CSS for the h1 tag and then see if it equals Chuck Norris jokes so it spins up runs checks it doesn't seem to be able to find it slow Superman and we have an error so error is timeout failure interesting let's kill that down and let's actually run that one more time so ng e to e and let me just glance over this note you can do by CSS dot get text and element title let's have one we'll run it it looks down into the terminal here I want to go time for a cup of coffee runs now it looks like it's stalling to query for it and find it which is kind of interesting I browser protractors felt right found time out waiting to find it so unfortunately my demo here for the last demo of the day's failing on us but we've been pretty lucky so far I don't think we're going to want to watch me debug a test live but some people might go yeah this is where the action happens this is the current page is not an angular application we are going to so we're going to take questions straight after the talk outside and if work out what the issue is you can come and join him but you can basically see the gist of how these tests work here so you'll navigate to the page you want to get and you'll use these helpers to select queries off the page and your one these tests so I think most likely my problem here with my test is probably something to do with my dependencies or something else here versus the actual code in the screen because I've run this a bunch of times but if we move back here over to our slides we did have a quick look at how we can run a test and we use the similar syntax here to actually and you can see the exact code here so by dot CSS here for the h1 and then we're expecting the title to equal and you can also run other tests so in this case here what I'm doing is I'm navigating to the root of the application and then I'm selecting the first joke and then I'm doing a button click and then selecting the second joke and expecting that the second joke will have been set onto the page so you kind of end up doing a few different things here in these end-to-end tests that you do so in summary they're not a unit test they run in the browser and they usually test a much more broader user story your motives for writing you for an end-to-end test they're going to be very different than testing a function and they help save a lot of manual testing you imagine you can automate a lot of this across multiple browsers and very aggression testing and large code bases they can be super invaluable and that kind of leaves us with like our summary of testing in our teams I guess is testing something that the whole team needs to practice and it's something they need to practice regularly it's not super difficult to do but if you're not doing it regularly enough you tend to be under pressure at work and you don't want to jump in and write the test because you're running out of time but if you do practice regularly they're not actually so difficult to to get in a habit of doing a lot of so we also run a lot of courses a lot of two days and three day courses so we have a whole much more than we cover now in our course work so if you want to get that for free you can use this coupon so you can see we have a whole bunch of course work that goes through using all the things that we've demonstrated in more so if you go to courses fire bootcamp comm you can go to end n-b-c - Sydney - 2017 is the coupon a last for and you try and actually click on the lesson and then you can put that in that coupon and then you've got access so I'll leave that open for a day yeah so everything you want to get don't forget Adams favorite color is green and we love green so we had a look at the tools that everybody's using today we had a look at jasmine and being the testing framework we looked at how we can fake dependencies with Jasmine spires we looked at the testbed API for helping set up our tests we had a look at async and fake async to help with asynchrony in our tests and we had a look at a couple of end-to-end tests thank you very much guys this is our twitter handles make sure if you say hi if you see it's a real conference and thank you very much [Applause]
Info
Channel: NDC Conferences
Views: 23,571
Rating: undefined out of 5
Keywords: NDC, NDC Sydney, Duncan Hunter, Adam Stephensen, Testing, Web, JavaScript
Id: lTKhB6uAmno
Channel Id: undefined
Length: 55min 48sec (3348 seconds)
Published: Mon Sep 25 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.