TDD Live Coding - Test Driven Development Tutorial with React, Jest, and Enzyme

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right so test-driven development with react react is a front-end framework that hopefully you guys would know if you're coming to this video and you're just a beginner with with any sort of programming you don't know any coding you're gonna probably have a difficult time watching this it's you might pick up something you might understand some of the concepts that we go through but honestly unless you know react and unless you know JavaScript with react and you don't have to know any of the unit testing or anything like that you don't need to know just you don't need to know enzyme I'm going to go through that but if you don't have any coding experience and you're coming to this is trying to become a beginner this is probably not gonna be a very helpful video to you okay this is really about a practice that we should be doing as software developers to be professionals all right to do our job to the best of our abilities so 100% software engineering love it thank you Rolando so there's a few things that I want you to we're gonna go over about TDD and some practices here so TDD is a practice it is something that you do it is something that you that you implement in the way that you build your software right it's some sort of practice it's the thing that you do so the first one so this is TDD the first thing that you do is you write a failing test so this may sound this is totally outlandish right this first idea you you first write a test that fails what what are you talk about are you talking about so the most common way that we do development right one way especially when we're starting out which totally makes sense especially if you're starting out is to just try to make the thing work right I've got this idea I want to write the code to make it happen so this kind of TDD flips that on its on its head because what you're typically doing in those cases when you do normal development I guess I shouldn't call it normal development but when you've kind of learn about programming you'll do this this kind of coding just to make things work and make things happen and then afterwards you'll add tests right so afterwards you might add to see if you even know what tests are right some of you may not even know what a test how a unit test works but essentially you add a test afterwards right that's kind of the more common practice you build whatever it is and then you write some automated tests in order to make sure that it does the way that you want it to TDD flips that so that you are writing your unit tests or your end-to-end tests or your integration tests before you write the actual implementation code okay so that's how TVD works you kind of flip that around so you start off with a failing test so you don't write implement an implementation code you don't write a class you don't write you know you don't write up a module you don't write up any of that stuff you don't write a function you know all right any variables none of that you write a test first and you intentionally write a test that fails you want it to fail the whole purpose is to make it fail because the next step is to make the test pass so you write a test that fails then you write a test then you write an implementation that causes that test to pass so it reverses that write it kind of reverses that the way that we typically do things and by doing so what you're what you're actually doing is you are forcing yourself into thinking from the user perspective right if I'm gonna consume a function how do I want to consume it if I'm going to if I'm gonna try to implement this function or this class what are some of the things that I need to I have at my disposal to give it and based upon that you start to draw out the design like you it's it's explained as kind of a whiteboard process you're kind of whiteboarding through the testing how you think things should work before you actually implement it so you kind of design this system incrementally slow and through these little tiny tiny increments but you do it a little bit at a time so you write a test that fails then you write the implementation code to make that test pass and then the third phase of TVD is refactoring where you go in and you say okay is there I want to clean up some duplicate code so there's the DRI principle you know give it a dry or you don't want to have you don't repeat yourself you try to look at ways to adhere to the solid principles you know if you're into the solid principles which of course I'm huge into solid principles when it comes to functional programming you can't really do the Liskov substitution principle or interface separation principle but that's okay still do single responsibility open/closed and dependency inversion so okay so you've got solid principles you get dry so you've got some refactoring that you do in order to try to make whatever it is that you wrote whatever the quick and dirty was during the green phase you now can reflect upon it to make it better and one of the key things that I think most people don't do during the refactor phase is name things this is one of the biggest points for me is you write a test I don't even necessarily know what the name of the test is I'm just gonna write it because it's a whiteboard I don't necessarily have to have a name then I make the code pass right I make the test pass then in the refactor phase I can actually start to think okay how can I improve this function well one of the first things I can do to improve a function is name it properly or if the way I have one or name a test is to give it a proper description so moving on that's basically the cycle of TDD you probably have heard of this before red green refactor write a test write the implementation code to make the test pass and then refactor the code to make a better implementation there are also three laws okay the three laws of TDD I don't know if you guys can see this but I'll read them out to you and these were created by Uncle Bob Martin first you must write a failing test before you write any production code so before you can write production code you must write a test okay so that's the red red thing right second you must not write more of a test than is sufficient to fail or it or it fails to compile so by the way a test that doesn't compile is a failing test right so you cannot write any more of the test then is sufficient to fail okay that's a that's very little tiny tiny increments that we're talking about very very small just enough for that test to fail oh and by the way not compiling is a failure right thirds third one is probably even more seen it seems more outlandish you must not write more production code than is sufficient to make the currently failing test pass okay so this is just kind of for the red phase and the green phase this is the three laws that you're doing you have to write a test first you only write enough of a test for the test to fail and then the third step is or the third law you can only write enough implementation code to make that test pass but only as small as little as you possibly can okay that is a cycle that you get locked into and you continuously repeat over and over and over again write a little test write a little production code fix it up a little bit write a little test write a little code fix it up a little bit write a little test write a little code fix it up like you just keep doing this cycle over and over and over again now the third one is kind of a cool one it's called it they call it ends aam be a rose on bees which I know I'm kind of blocking part of this I can't really get out of the way I should just can I drop my camera I'll just hide my camera there we go there we go okay so the third one is called zombies which is kind of a way of thinking about what the next test is that you're going to write can you zero you need to write for the test case of zero things being passed to your function or zero things being returned then you start thinking about one thing returned or one thing being passed as a parameter and then finally you get to the many okay so you're you're kind of using this process of end zombies no think about the null cases think about the zero cases think about the one cases think about the many cases and then the boundaries interfaces and exceptions are where you start to you got to obviously think about boundary behaviors boundaries of those behaviors so that's kind of where the ends on the ends eom comes from is that you're kind of stretching out the boundaries of the code okay then you're defining interfaces if you're working with some sort of object-oriented programming you're gonna have interfaces but you can also think of these interfaces as how do you want to you know name these things how do you want to accept the parameters those sorts of things and then the exceptions how do you want to throw exceptions how do you want to handle exceptions so that's the three practices of TDD that you should know about okay the write a failing test make it pass and then refactor then there's the three laws so you have to write a failing test before you write any production code you must not write more of a test than is sufficient to fail and by the way failing to compile is a failure and then three you must not write more production code than is sufficient to make the currently failing test pass and then finally when you're thinking about which tests to write next you're typically going to be thinking in terms of n zombies so what's the null case what's the zero case what's the one case what's the many case and how are we stretching the boundaries how are we defining the interfaces and how are we handling exceptions okay and you're always trying to do simple solutions with simple scenarios so okay all of that my goodness [Music] where's my camera or my camera go there we go yeah I'm back Steve's back okay sorry I got I'm technically still I shouldn't say on the clock I'm not really on the clock cuz it doesn't work that way but I do have to keep an eye on business and this is a live stream that I decided to go on during the day so okay so hopefully everybody's got the three practices down right red green refactor three laws and zombies we will be referring to these occasionally throughout this throughout this video so let me just get my screen set up so that I can go through the lesson so the first thing is we're going to want to we're gonna start off with a blank react application so we're gonna go ahead and do let's change into my projects folder this is where I like to hold all of my projects this is so for those of you who are not familiar with what we're looking at this is a bash command line this is a special one installed for Windows it comes with git so it's called git bash and I have it set up with my Windows terminal so this little special terminal that they have that you can do dropdowns you do all sorts of different ones I have ever been to installed on here I could do Ubuntu instead for my bash command line but I am using the git bash just I love the interface I think it's great so that's the one I went with okay so these are gonna be bash commands that I'm gonna be typing and occasionally so you'll if you're used to Windows development some of the commands might look they're very very similar but some might look a little different most of everything I type here is going to be the same though so we do need to create a new project so we're gonna do let's see I'm going to do NP x create react app and we're going to name this thing so we're just going to do a very simple example it's gonna be called a person app so we're going to say person app and that's going to go through and this is gonna take forever to install so I probably could have done this while I was going through all the different practices but while this is going on so we've got let me talk a little bit about testing in general as far as so some of you may have seen the pyramid the testing pyramid heck maybe I can pull up a graphic of it let me find it here testing pyramid pyramid see if I can find it here ah that's not it okay so here's this an example of the testing pyramid you you need to understand where you're testing what you are testing and how it fits into this pyramid because the UI testing is gonna be the slower test these are what we often call end-to-end tests where you are testing kind of the complete system from top to bottom so if a user clicks on this button it's gonna go you know talk to the API and the API is gonna go hit this hit the database the database is gonna return some data that gets formatted by some sort of like entity framework or some sort of ORM then that gets returned back as part of the restful api which were translates over to json the react application is gonna you know fetch that it's gonna take that json you have to convert that into an actual javascript object that has to then be you know displayed or passed in through like redux in order to you know if you're doing global state management through redux then that's gonna have to go through all of your reducers and actions and stuff and then finally we get something that comes out of it right like that's that's a lot to go through so you're testing there is going to be much much slower where we out on that so you need to make sure that you understand what you're testing and how it's gonna affect the speed in which you're testing the service tests which we typically call integration tests are where you're kind of looking at the different layers and seeing making sure that they're interacting with each other properly and then the third one is unit tests where you're really trying to encapsulate just this one little tiny piece and and making sure that the completeness of that little tiny piece is exactly how it's supposed to be right so you're testing inputs and outputs so basically unit tests are kind of were traditionally you do TDD from because you're you're building things small and incrementally it makes sense to do so from the unit test foundation and you can kind of learn and explore as things start to expand beyond that one little test that you wrote or those little test Suites that you're writing you kind of learn how what are some of the other actors that I need in this system in order to make the whole thing start to work okay so you start kind of doing these unit tests but then you start adding these integration tests to to check those integrations of those different units and then finally you kind of build these end end tests that's the more traditional way they call it the chicago-style or classical it depends on or traditional kind of depends on who you ask with chicago-style which doesn't really make much sense I prefer personally the term inside out inside out testing you start with the smallest inside thing at the lowest level and then you kind of build up from there you go inside out right the other philosophy is outside in which is kind of the reverse of that where you start with the end-to-end tests and you have this essentially a spec that you need the system to eventually complete so you start with that and as you're saying okay so this is gonna do this you start to determine what all the actors are in order to make that happen but that one test is essentially kind of guiding you along the whole trail to the end and determining what all those actors are and you kind of build the unit so long as you go you kind of start out with this and intestine as you start to build these things you add unit tests along the way to help build those things and that's kind of a different philosophy but there's a lot of similarities there it's just more mostly a matter of whether or not you have an end-to-end test in there so we are going to hopefully everything yes everything is installed so here we have NPM start NPM run build NPM test NPM run eject and in order for us to get started we need to do this change into the directory of person app so let's go ahead and do that we're going to change in a person app now what I'm gonna do is I'm not gonna start the application I'm going to do NPM test and this is gonna run all of the tests that are in the application and if we take a look we see oh no tests were found hmm interesting since the last no tests found related to files changed since last commit okay so this is kind of cool because just has a watcher so we're running tests ingest right now it found no tests didn't it I should say it found no new tests it's got a watcher so which watches to see if any files will change and if files change it will automatically rerun the tests once it sees the change and I'll do this if you change a test or if you change the implementation code it knows it's watching all these files this is anything changes it'll run those tests again if you want to manually trigger it you can just type a from here and it'll run all the tests again okay so we're gonna see this screen up pretty regularly and there is a test in there it's one passed and I will show you that it's in the app test j/s file so let's go ahead and I'm gonna cancel out of this I'm gonna type in code period and we're gonna open up our application in Visual Studio code and it said that it found it in app test j/s and if we take a look in there there is a test that is passing okay so there's a way of writing tests that we're gonna go through this is the first one this is the one that comes out of the box you can use the word test in order to define a test you can also use the word it which is kind of the more popular way to do it because as you'll see the syntax of using it in the way that we're going to be writing on our test suite is gonna make a lot more sense and it's gonna read properly it's going to kind of read more like regular English when we do it but it says basically it renders learn react linked so we're checking to see if it renders the learn react link we define a constant which is to go get the app component then we link elements get by text so we use the get by text to find this bit of text and then we expect which is our assertion here that the link element is going to be in the document okay it's got to be somewhere in there so this is all good and fine but there's a couple things I need to do here the first one is I want to add a I need to add a jeaious config file to give us a little bit of some intellisense and I'm just gonna copy and paste this because I don't want to have to type it all out for you guys but essentially it's gonna be this its type acquisition you need to include just okay and this is pretty easy to find out there if you're looking for just type in intellisense with jest and you'll find out how to build this Jace J's config file but now that that's in there that's gonna give me some intellisense on just the other thing that we need to do is we need to install enzyme and enzyme is a special library for wrapping react react components and gives us a little bit of a different interface in order to work with those components because right now we're just using jess which doesn't it just is a more generic testing Runner and framework whereas enzyme is kind of a special library specifically built for working with react applications so I'm just going to open up the terminal down here so that we don't have to you know flip back and forth between screens and I'm just gonna type in NPM I D and this this big capital D means is basically short first saved save dev enzyme is the is the packet we want to install so this is going to install the enzyme library for us and I can just show you guys here we take a look at the package.json file in the development there is dev dependencies you'll see there is now enzyme and that's what we're looking for we need enzyme to be in there so we'll see enzyme will see by the way just the dependencies for just come with react from with the create react app so that's already installed but in order to get enzyme we have to do that command okay to add it in there alright so now that we have enzyme cool Co cool I'm going to get rid of this initial test I don't want that anymore I'm gonna write my own test down I'm in the red face I need to create a test that fails that's the first thing okay I need to create a test that fails so what I'm gonna do is I'm going to actually let me you do I want to let me talk real quickly about the Dom well not really Dom but the the the react component tree so we've got this index dot JSP which is gonna be loaded into the application first right on the page then we are including it in our react on render so this render function is going to actually render these components to the page okay so render you're passing in these things and it looks a lot like HTML but it's actually syntax called JSX and we are putting our app component inside of this thing called strict mode which I'm not going to get into that at all but essentially you're putting the app component you're displaying the app component on the page okay that's what's essentially going on you know what let's take a quick look at this you guys may have not seen what a react application looks like out of the box when you just do the initial install so let me get this thing kicked off it looks like that that's what we have to start with okay very simple but this is that app component ok the app component is being rendered on the screen right now and so we've got it here indexed is has this react Dom render which is including the app component then the app component is gonna be this little doozy right here this is a functional component out of the box we'll talk about that a little bit later but essentially there is what looks like HTML but it's actually JSX and it gets converted into JavaScript into react components so yeah but it's meant to look a lot like HTML so it's it's gonna look like we're dealing with HTML but we're really not okay that's wrong hey there we go so that's what we're seeing there I'm gonna actually get rid of everything that we have so far as far as the header and the link and all of that I just want to start out with a div labeled app all right my viewers fluctuate I'm not sure if that's a good thing okay so what we're gonna do here is do did you we need to write that test first right so we need to write our first test you start off by creating a suite okay you need to create it's a suite around a particular system under test and you start by creating a suite you start you create a suite by using the word describe okay now when you're doing describe you need to pass it in a string and a function and the string is going to be a label for what it is that is this the suite is covering so typically this is just going to be the system under test itself so I just like to say app so we're gonna describe app and then we're gonna say in a function which I'm using the arrow syntax function we're gonna say okay we need to describe a functionality a behavior of the app component and so we're gonna use the it function which these are global functions provided by gests so just has these components has these these global functions that we can call upon described and it along with some other ones like before all and before each which we might talk about a little later too but essentially we now need to do very similar town we'd to describe where we said a label for this thing and then a function that we're passing in once again with it we give it a label and then we provide a function so this is now described is our test suite it is our first test okay and right now it doesn't look like it's doing much but I can actually run NPM test from here and we should just basically have a passing test right we sure do all our tests pass because we don't we haven't said anything we haven't set up any sort of assertion to fail at this point okay so we need to actually write our test to actually test the behavior so what we're gonna do is we're going to say now I like to wait to label my tests I like to make that part of the refactor phase but what we can do is we can define a constant called app wrapper that is going to contain the result of going and getting the app component okay so we want to go get this app component so that we can inspect it it's sort of like when you're like create an instance of the class for me go create an instance of the component for me so I can inspect it okay so to do that we're gonna say shallow we can talk about what shallow is in just a moment but I essentially now want to say the app component is what I want to wrap so I'm creating a wrapper around the app component okay so the app component is what I want to go get I'm creating kind of this instance of the app that allows me to inspect the app component we call shallow in order shallow is a way of basically forcing it to not load the entire child tree of the app component we're only loading app that's the only component that gets loaded because when you're dealing with to react you have typically some sort of tree like structure of here's our app component and then all the other little components that can be displayed on our application kind of branch out from there okay and I'm saying I don't want to just I don't want to get the whole Brandt all those branches and everything all I really care about is just this one app component and that's what we're going to inspect okay so we're gonna go shallow on app so this means don't don't render any children of the app component only render the app component itself and we're gonna inspect it that's essentially what shallow does now there's gonna be some problems though because we don't have something called an adapter installed shallow is not defined I haven't brought in shallow so shallow is a function I need to bring in from enzyme so I'm just gonna do an import from enzyme of that shallow function we can get rid of render because we're not using the testing library that comes with react we're gonna use enzyme instead okay so that's in place now that we've changed our code notice that the testing framework still continues to run okay now we have a new error import adapter from enzyme adapter react 15 so I'm actually going to run the adapt reactor enzyme adapter react 16 because I'm running react 16 so that's what I'm gonna add to do that let me pop out of this and we are going to let's run NPM oops I'm in the wrong screen there we go NPM I which is short for install once again we're gonna do the capital D to put this in our dev dependencies and then we want to do let's see what was it called it was uh the Riggio or do I know I had it in here there it is enzyme it was that command we saw the library was asking for right enzyme adapter react but this time instead of 15 I'm gonna do 16 and I'll tell you why it's because if we look at the package.json file will see that react is version 16 ok react and react Dom are version 16 and so the adapter we want I think should be for version 16 I think 15 will work but I don't want to try I just would rather go with the correct version so ok now that we've got that in place the the next thing that we need to do is actually set up our configuration of the adapter ok so we installed the package now we have to go create an instance of an adapter for enzyme to use to wrap that app component so what we're gonna do is there is already a file here we go set up tests this is where you can where jess is going to kind of set up the tests the test Runner essentially and we want to add an adapter for the test runner so we're gonna say configure and the function we want to call or we want to pass it the object we want to pass in to configure is object that has a property called adapter and the adapter we want to set up as a new adapter now I think we have to import yeah we have to import adapter from enzyme as well except it's going to be that import adapter so this adapter object that I'm bringing in is gonna come from that enzyme adapter react 16 so this is the adapter for react 16 that we're creating an instance of okay and then we're doing the configure function because that's what enzyme uses in order to figure out which how to connect itself to Jest okay so just as the test runner just needs to know what how to talk to this react application it's already got some typical stuff that it usually works with but we saw that I just deleted that like I deleted the react testing library I shouldn't say had to leave it I just didn't import it right and instead we're using enzyme to do this and so I'm gonna bring in this adapter alright Wow to hold views I'm taking a long time to go through all this stuff so that's kind of the thing about me I like to explain everything as I go along and it takes me a little bit longer to go through and I think some people kind of lose interest because I go so so in depth but okay so now that I have that in place what happens when we do NPM test hooray we are passing okay all right so now we wrote just enough of a test to fail then we implemented the code just enough of the code in order to make it pass we actually completed our first red green cycle and there's really nothing to refactor here we can evaluate it Oh actually there is something to refactor there's almost always something for me to refactor I always I keep forgetting to do this though it does not have a description so what I'm gonna set this to is renders without crashing and whenever you make a change you should always rerun your tests which automatically does which is really handy and we still see that it passes so even the thing that we're starting to get from doing this practice of tests make it pass refactor is that my application is in a working State right and if I if I wasn't sitting here describing and explaining all this to you that whole process would probably take maybe 30 seconds right to go through the red green refactor and and everything would take 30 seconds or less so that's the kind of cycle that we're trying to engage in over and over and over again ok so let's move on to the next red phase let's actually figure out we want so but I would like this application to do and I haven't talked about the design of this but the initial intention is I'd like to have a list of people that I can edit so I'm just gonna have a list of people on my page a list of names with an edit button that I can click on that will take me to a page that I can edit that person that's all this that's the only use case a very simple thing but I'm trying to kind of drive this whole thing out for you guys and explain it along the way so what I'm going to do you know what I don't like how this is taking up half the window so maybe I will kind of switch over to let's do this I'll keep this window up as my test runner so that we can all flip back and forth to it I typically work with a larger window so I can have the tests running on the bottom but for this demonstration in order to make everything clear I've expanded or made the screen a little bit larger so but I need that screen real estate to work with for my coding so we'll we'll do that so now I need to write my next test we've completed one cycle it's not now we're back in the red face we need to create a test so we're gonna do it again I don't know what exactly it's going to do I don't have a good name for this yet okay of how I want of I don't like to give it a name until I actually have the code written because then once I have the code written I know what it's doing and I can properly label it like I don't know it seems like a fully foolish thing to a lot of people and when I talk to people about this all the time they're like what are you doing why you should already know what it is you're testing why don't you give it a name I'm like well because that may not actually be the test that I write I want to write a test first and then now that I know what the test is I'm going to have a way to properly label it so anyway I'm gonna write my test now even though I don't have a name for it but what I do know I need to do is I said I want this application to display a list of names so obviously this app component is going to need to display some sort of component that gives me that list of names so let's do that let's uh let's say I'm gonna need to take this Const app wrapper I'm just gonna copy this so there's my app wrapper then on my app wrapper I'm going to find there's a special function called find that comes with our enzyme right that allows us to pass in a component that we want to find on the app component so we're saying I'm wrapping up the app component and then I want to find on that app component another component and I can pass in what that component is the the component that I would like to see let's now we can kind of add it now we can start to make some design decisions what should I name this component that it should find on on the app component I'm gonna say person list okay now obviously once again we look at our tests this is going to fail of course it's gonna fail because we don't have a person list remember part of part of the second law of TDD is that you write only enough of a test as to fail and right now we have a failing test because of course there is no such thing as person list so how do we then go and make this pass well we go create a person list so great okay let's go create a personalized person list a s and I'm gonna do something really what some people is think gonna be real dumb but the third law of TDD is write only enough of an implementation as to pass the test so I'm going to do export default that's it that's that's all I'm gonna write right there and watch oh I gotta import it and still doesn't know a person list is but so I have to go back here and I have to say so my test I can close that down my test needs to know a person list is so let me add that import person list from person list okay it's still not going to pass though because this is looking for personal list on the in the app so I need to go into the app component and actually just add okay you're going to call person list great right person list is all in there now let's take a look at our test I think I still need to import on my app component yeah I still it doesn't know a person list is so there we're still having a failure so I need to I'm gonna get rid of this logo because we don't need that I also don't need the app CSS we can get rid of that but I do need to import the person list from person list oops okay so now that that's in place aha we have tests that pass whoo-whoo-whoo were we just finished up the green phase right so we wrote our first dart well we wrote our second test that failed and now it's passing now you can still think of this as the refactor phase or is another III think that this is another red green refactor phase but we still need to finish up this test the test is not done yet because I don't have an assertion I need to create an assertion so what I'm gonna do is let's do expect person list so what find is going to do is go find that person list but we can we can get it as kind of an array so all of the instances where this person list is found can be thrown into an array so I'm going to define this as my person list and then we can inspect the person list to see okay I should only have one of these right I should at all as something I can test that I can assert I should to be able to say I should only see one of these person list components so we're gonna say expect person list to have length of one which basically means check that the person list which should be an array make sure that the length of the array is one there should only have one element inside of this person list array and that should still pass yep and I'll just double check again we are still passing yep okay so that is now a completed test with an assertion and now we can move on once again into our next read phase so actually oh refactor got a refactor it says yes must refactor what do we want to call this renders a person list good enough okay so now we have that next step let's do yeah what's the person let's gonna render what is the person okay so how does the how is the rent how is the list going to get a set of names okay so we said that we want this list of sets to show some names we need to define some names somewhere okay where do we want to define those names well we could go all the way into a Redux solution but that's that's a little bit beyond this and that's not a very simple implementation the thing that makes the most sense at least at this stage of the development cycle of the development process is to just create some sort of object at the root component just create some sort of objects that contains all of the names right or an array of names so again I know that that's what I want to do but do I just go right into the app component start doing it no I need to write a test first that's the whole point of TDD write a test first so what I'm gonna do is I'm gonna write my first test for this particular I'm gonna write my first test I'm gonna write a test again I don't know exactly how I want to label this we'll do that in the refactor phase okay so what should the app component be able to do we know that we want it to contain an some sort of object for person list but that means in order for that to happen the app component has to have something called a state property so let's just double check to make sure that the app component has state we can do that by doing apke map wrapper state and let's assign the state to some sort of variable here we'll call it Const app state okay so we're defining appstate and we're setting it to the state on there okay let's take a look at our test and see oh we have a failing test shallow wrapper state can only be called on class components so state does not exist on functions on functional components which if we take a look at our app J's file it is a functional component it is not a class component so I'm gonna fix this by doing by converting this plot to a class called app which extends component which I'm going to import above here from react and then I need to change this return to render all right now let's take a look at our tests and we pass okay good so now now that I have that in place I need to make sure that that the state so now that I know that I have state I need to determine what so remember we going back to zombies going back to this thing here zombies zero one many but there's an N also there's n za bees which means new or null okay so I want to have in zombies my first test that I want to write for this to check the state of the app is what if I have no people what if I what if my state is null okay that's kind of the first case in area that I wanted check for so that's what I'm gonna write for this for this assertion I'm gonna say expect that the app state should not be null because I don't want to be null that's the case right I'm looking so what it what what is the when I'm looking at n zombies I'm looking at n n is saying null what is the use case around null null is something I don't want in my state that's what I should be testing for I want to test what happens if it's null null should not be of okay that it should fail that I want there to be state otherwise we've got a problem okay so by doing that now uh-oh we're back to a failing test okay so in order to make this pass what do I need to do well I need to add a state I mean it's look at that they expected received to be normal and it received null or to not be null and it received null so if something's clearly wrong here how do I fix that well let's go back into our app J s state property set it to an empty object now let's take a look at our test and we're passing because now it's not know anymore okay so the next case is gonna be what what do we want for let's see do we have any refactoring because now we have a passing test let's go to the refactor yep so what do I want to call this let's say when did I give this in my notes I said oh yeah just head of state there we go okay does that refactor cause a problem no it's still passing okay good good deal okay next up we need another test we're back to the red phase I don't know what it's gonna be called okay so the next thing is we have nothing useful for the people list so let's add some people to the property state shall we let's do that to do that let's do so we need to on the state we need to say okay how are we gonna store people we know that we want a people list this people list is going to be on the state of the app component so we need to check to make sure that that people property exists on state okay so we're gonna do once again Const app wrapper and then we're gonna say Const appstate so we're gonna take actually this lending I should copy both of these lines huh and then we're going to expect that app state we should on app state be able to find people right so I should just be able to find a people property on that app state so my assertion here is gonna be you hey that people properties should be defined there should be a people property on here so we're gonna say to be defined and of course that is a failing test because people property does not exist on state yet right received undefined okay so since that's undefined let's go back into our app how do we fix this what's our green phase well we need to add a people property which I'm gonna initialize this as an empty array and now we go back to our tests and we're passing green again okay now we're going back into the refactor face and I think at this point you guys have seen me do some redundant things right so we can start to evaluate some dry principles or just some just what are some ways that we can clean this up and I think this is an obvious one I have called this app component with a shallow wrapper in every single one of my tests so there's got to be this redundancy is something that I should probably try to eliminate and what I can do is before all of my tests I can say before all I want to take an assign to this constant app wrapper oops that wasn't what I meant to do so before all of my tests run do this set up the app wrapper now the problem is the scope of this is inside of the before all I need to move this app wrapper out here and then I can assign it inside of the before all now that I've done that or create a proper ice ice but either way so before all of my tests run I'm going to create this app wrapper thing and now that I've got that app wrapper being created before I do any of my tests I can essentially eliminate it from all of my tests which makes this test completely useless so I'm gonna delete it okay then I'm gonna do this one and this one and this one so I just refactored out a ton of code out of my tests by the way double check am i still passing oh no I'm not because oh I said it is a constant that's right you can't do it as a Const and I do it as a let now my tests are they passing after my refactor No what did I do wrong what did I do wrong oh I know what it is there is no statement of what to do that's right there's no label for before all there we go just have it I'm so used to giving everything a label but there we go so now before all of our tests of this refactor of moving app wrapper to this let and doing doing the assignment in this before all all my past among all my tests continue to pass and all my code is still in a good working State now I can also go back and refactor this and say so we're gonna say has a people property on state okay so there we go there's my next that was my next test by the way I just refactored every time you make any sort of code change go back to take a look at your test yes everything's passing okay so now what's our next test what's our next test we need to [Music] we need to make sure that the people does people property is being passed to person list because the person list needs that list of people right in order to render whatever it's going to render so we got to make sure that that passes now again I could just go right in here it's very tempting it's very very tempting to just go right in here and add the assignment of people as a as a prop right it's very easy I could just do that right now no problem but we're in test-driven development which means I need to have a test around that first before I write the code so I'm gonna go into app tests again say it I don't know what yet I sort of do but I don't know what to name it okay what am I gonna do well I'm going to make sure that this person list thing that I can go and get which we saw I can do this here to go get that person I'll just copy that and paste it here so I've got my person list I need to make sure that on the person list that property of people the people thing is being passed in as a prop to this person list component so I can I can enforce that by doing and expect oh by the way let's just double check make sure I write that line of code or are we still green yes we're still green okay so I don't have a failing test just yet I have to do my expect the person list okay that person list dot props so props is a function that I can go and inspect what's going what's being passed to the person list as props I'm going to get this list of what are the props and on it there should be a people property on it right there should be a people prop and not only that but it should equal the same people that were that's on my state so I should be able to look at the app rapper and say look at the state and there should be people on it right so those two things should be the same they should be equal and now when I look at it of course my tests are failing because an expected an empty array but it received undefined okay so now I have a failing test what can I do in order to make it pass well we go into the app component notice I am not doing anything with person list it is still just this empty function that gets returned that's kind of the isolation that you're doing with that shallow wrapper of enzyme is you are not looking at what's happening with the child you're only looking at what the app component itself is doing is it passing these people as a prop to that other component okay we are and we found out it's not so we need to create that people prop and we need to send it this dot state dot people okay now if we take a look at our test we're passing great is there anything to refactor they're almost always is something to refactor for me because I like to wait until the end to give this thing a label so I'm going to say passes people property of state two [Music] people are personalist as problem okay now I've given a accurate description of what the test is actually testing patbernard says see all your access videos big fan of yours since then you're you definitely know how to pass on your knowledge Thank You Pat I appreciate that I'm surprised I've got 12 viewers for what I figured was gonna be a pretty boring lecture here but I'm glad you guys are with me so thank you so much okay so there's my refactor oh by the way since i refactored what do we do we always go check make sure the tests still continue to pass after a refactor which they do okay good so next step we need to make sure that okay so maybe pass people to see print okay already done that next one is we want so in order to create the person list okay so we have have essentially done just about everything we can to this app component okay we've we've created some state we've added a property on it of people that's going to contain people values we've made sure that there's this person list in there we've made sure that the people are being passed to the person list right so we've got a whole bunch of tests around all of that functionality the tests have driven it out and again one of the great things about this right now is we know that this application works if I wanted to go run it right now I could I could do let's cancel this I could go run my application it should work because all the tests pass right uh-oh means a return statement visiting or to render nothing oh that's because I still don't have okay look at me being a liar it's because I don't have it it's it's not rendering anything right now right it's there's nothing to render because I made that that component just a function so it's complaining about the fact that I did this it doesn't like that at all it needs something to render I'm calling this person list but my tests passed because as far as as app is concerned that is done properly but now I have to go inspect this person list which is currently not really working and I've got to make it work so I love how it just called me a liar if I had done if I had done something a little bit more simplistic like if I did this which is really what I should have done with this like to do a proper like starting implementation I just wanted to show you initially how you could make a test pass by doing this simplest little thing and now it just fit me but I could just do this that's that's also perfectly valid to do and it should now compile and everything and if we take a look at let's bring this back over localhost 3000 now it's not going to complain anymore because now I gave it a valid thing to render and in it understand that that person list is something that I don't have any tests around so yeah I need some tests around that that's probably where we're gonna head next but you'll see yeah even though it's a blank screen it's at least not failing and if we take a look at like the console there's no errors so this is doing just what it's supposed to do and we have a working application okay I'm gonna revert this back though cuz like I just kind of want to do that we can close out of this I think that killed it right yeah okay come on close there we go vs code is slowing down on me Oh No okay so now we need to start looking at this person list which means right now we don't have any tests around personalist so let's go and create that so the convention is to add there's actually different ways you can add tests to the application you can create like a test folder and just stuff it all in there I prefer putting the tests side-by-side with the implementation code so wherever I have my personal list is also where I have my person list test so in here what we want to do is we need to start describing this person list right so we need to do some imports let's import react from react I need to import that shallow function again from enzyme and we need to import person list from this current directory alright now we can go ahead and describe so we're creating our test suite the thing that we are describing is the system under test which is the person list and we're gonna give it an arrow syntax function here and we're gonna write our first test it it what what should it do alright I could write my first test with us terrible there we go so my first test could be and probably should be just making sure it renders right but I'm gonna go one step a little bit ahead just to kind of save time save time and I'm gonna say Const person list rapper is set too shallow of that person list component and what I want to do is I want to so as part of my design of person list I'm just gonna make this a simple little unordered list so I'm gonna make sure that there's an unordered list component that gets rendered on this so I'm gonna say personalist expect person lists No Oh personalist rapper there we go that's the one I want to I need to actually need to find I could actually do this up here so I'm gonna do kind of how I did it in the first one I miss a Const people list ul will say is from person list rapper dot find assign this person list rapper find and I want to find a ul element so this is another one of the ways that we can select an element on the shallow rapper so we saw just to give you a comparison when we did this app test we wanted to find personalist we were passing in the actual class or I should say the the module right this object called person let's go find that person list thing but you can also as a selector just say hey I want to go find an element by this name go find a tag called ul and again this is going to put in this is going to be a array of sorts right it's gonna be type as a collection so on that people list what I can say is rather than person list rapper I'm gonna say people list you ELLs there should only be one of those so to have length of one now of course this is going to fail as we take a look at our tests and yep there's our failure I expected the length of one received zero so we need to somehow make it so that my person list returns an unordered list let's go ahead and fix that right now wow that was really hard I there's my test failing for some reason Oh reacts not defined that's right I need to since this is JSX I need to bring in the react library to make this work notice that the test suite is helping me identify all my errors right this is the great thing about test-driven development is like every single thing that you do you have a test that's telling you when you're doing it wrong because you wrote a test first to tell you how to do it right so good okay well now we're passing we could switch back over do we have any sort of refactoring so one thing I could do so that was the simplest thing some of you might be tempted to do kind of this return like if I did it this way it's arrow syntax function is kind of one of those things that not everybody totally understands I could have written it this way and that would be perfectly acceptable that's kind of the more long way and notice my tests still pass but whenever you're doing arrow syntax you actually if you're only doing one thing in that function just one line of of commands you can just drop the return statement altogether and just do the thing right so that's what we're doing there the only reason why you use curly braces is to define scope of multiple things to perform that's the only reason why you use curly braces and pretty much I mean it's not I'm not gonna say universally but that's kind of what you do in a lot of lines but yet we're still passing with my UL just being right here on the export default so we're good to go next thing we want to do is we want to go back to the idea that okay what if there is zero so null 0 1 right Zombies null 0 1 many okay so the first use case is gonna be I think just I don't know how I feel about IDI and it only comes into play once in a while I'm more of just straight Dom bees like 0 but um so if we go I'm gonna close app test and a promoter because I don't I'm not working on those right now I like to kind of keep my desktop a little tidy so I know what oh look at that I forgot to do during my refactor phase CAD Steve you gotta stop doing that uh renders a ul element okay good enough and I refactored so just double check passes all the tests yes of course it does because all I did was add a label next up it do to do to do do hope you guys are enjoying this stream it's a little different for me this is an actual way this is an actual lesson that I would give like this is an actual I'm I'm kind of roughing out the edges here with you guys but this is actually what I would be doing in my day to day job so awesome stuff right you guys get kind of an insider glimpse into what it is that I do okay so we've got it let's see we're gonna do const so okay let's talk a little bit about what we need this to do next so we now have this unordered list now what we want to do is display for all those people right we have these this people array being passed from the app component down to person list what we want to do is we want to make it so that people right that that those people are being displayed inside of the unordered list and we do that by creating an Li element for every person so to do that let's start off with and this is going back to zombies what if I have zero people what if I what if that people property has zero people in it which right now it does so we can just go ahead and say let's create a Const person rapper person here just copy this up here do actually will do both of these I believe I need no actually don't I don't need that ul because I can find the list item elements from the personalist component itself so I'm gonna do this you're welcome Pat thank you for hopping on board here okay so now what we're gonna do is we need to say okay so I've got this person I need to look for all of the list item elements so I'm gonna say Const people list items and this is gonna be on that person list rapper I'm going to find all the Li elements so again this is gonna give me a basically an array it's gonna give me a collection it's not really an array I don't I don't think technically it's an array yeah it's just a shallow rapper HTML attributes it's a collection who had a smart question asked right now uh well that's okay Pat I appreciate you following along like I said this is what I do it like this is upskilling this is if you know how to do tests if you know how to do react if you know how to do software development in general but you've never done test-driven development that's what I'm trying to show you right this is a type of practice that you should be doing in your daily life in order to make your code better right we're making code better by doing testing first and making sure that all of these use cases are covering the the performance of the application so what do I want well I want to make sure I expect that that people list items there should be there should be zero of them right there should be none because people should be empty and just to be absolutely sure of that let me do this I know that that person list from the app test we were saying it should be handed a list of people right we're saying it's gonna be getting this thing this prop called people we know that from the test so I'm going to just doubly make sure with an empty array that I'm going to pass along okay now failures yeah we have a failing test yay we have a failing test we have something to implement what and hey oh darn I got so excited and the reason is because obviously right if I don't have any people how many list item elements is person list returning zero so it's going to pass the test mmm we did not write a sufficient test in order to cause a failure however does that mean that this test is not a good test no actually it's quite a good test we want to make sure that when there are zero people being passed to this person list we get no list items so this is a perfectly valid test so I'm gonna say I'm gonna I'm gonna leave it in place here there's nothing wrong with it renders no Li elements when no people exist okay I refactored check out the tests yep everything still passed by the way notice that we have two sweets that passed this is because it detected two described functions so each sweet is called is the each described is called a sweet and then inside of the sweet we have all these tests you'll notice I have two sweets with a total of six tests between the two sweets so everything is passing okay all ran all unit all test Suites and everything passed okay hold on here I got a double check something sorry I like I said I have a little bit of I got slack still stuff going on at work that I have to just keep an eye on yes I will make this available after livestream so Abraham chillon I will make this available because obviously not everybody can sit here for a couple hours and watch me do this some people have to work so yeah absolutely okay uh I don't need this anymore let's get rid of that okay so we have our zero case now we need to figure out what's going to happen with our one case right zombies so we're gonna do it again I don't really have a good name for this yet I don't like to give things labels until I know what to label them I have a vague idea I know that I need to go to this one right so we need to create one really what I can do is just take this whole code right here and paste it in here and say actually if I have people let me give it a person here first name what did I put oh yeah okay of course who would be the first name Allen last name great okay so now that we have a person in our people array that's being passed to our person list we should expect that when we go find our list items there should be one right if I have one person I should get one list item and now because I have that test in place let's check to see if it's passing oh no it's not only that one and zero right it's expecting one it's getting zero well of course you dummy right everybody's like of course dummy you don't have any list items being rendered so what can we do in order to fix this well well that work will that work hmm so look carefully at the what's failing now the one test that I just wrote or the the one test that I just wrote is now passing but this is a different one that's failing expected length of zero but found one so now that test that we wrote to check for zero isn't such a bad test after all is it hmm so instead of list I elements and just going straight into it let's do this let's go back to a return statement we need to have some sort of logic here actually I'm not gonna do return there I'm gonna do let's do an if statement the check to see we need to check how many people are being passed in right that's the condition is that people has to be checked so typically we would do this as I'm gonna do this as props it's kind of that the typical way did you do it as you do props so I'm gonna look on that props object and look at the people prop and I'm gonna check to see if it is if it exists at all because it may not be getting a people prop at all maybe there's it doesn't it's not even being passed so I'm just gonna assume that that's gonna happen so if there is a people then what I want to do is I want to a return this and if not I'm just gonna return oops that just single unordered list will that work hmm will that work let's take a look at our tests mmm we still have a problem with zero and that's because we are somehow still getting to this if people exist if I'm passing in people and and somewhere it's this thing right here because I am passing a people but it's an empty array I shouldn't have any list items when I'm passing an empty array but that still means there's going to be a people prop it's going to exist it's just gonna be empty so I need a second check in here the checks not only if the people prop exists where it is defined but I also need to make sure that props dot people dot length is equal to one okay again simple as possible implementation you may be thinking well wait a minute what if you have more than one people that's fine we just haven't created that use case yet there's no guarantee that that's even gonna be a part of what we need to do at this stage okay so I'm not gonna start writing out complex code to match a use case that I don't even have a test for I'm gonna only write enough code remember that second law or actually I'm sorry the third law the third law of TDD you can only write enough production code to make a failing test pass I do not have a use case I do not have a test around multiple people so therefore I cannot write implementation code around multiple people I can only do it for one so I'm checking out this one person okay great let's take a look at our tests oh look they're passing yeah we're passing okay so is there some refactoring we can do I believe absolutely there is some refactoring we can do there's a different way we could write this there's actually several different ways we could write this component I'm going to I'll do that a little bit later there's another refactor I want to get to a little bit later on but for right now what I'm gonna do is I'm just gonna do this I personally I prefer I like functional programming to be written in such a way that there is only one command being executed per function if I can find a way to refactor my code so that a function performs only one thing I love single responsibility principle I'm gonna have one line of code that it executes how could I do that here how could I do that well the way I can do that here is I'm going to move this unordered list up here and then inside of the unordered list I can put this logic but I need to do it in in a different way an if statement could be rewritten as something called a ternary operator so I can do that by saying these two conditions take those out stick them in there and I'll drop this down so you guys can see all of it it's taking up a lot of screen real estate move all this down just so you guys can see what I'm writing here so I've got an unordered list that checks these two conditions and then I can use the ternary operator to say if those two things are true up so people exist and there's a length of one then I want to include one of these li elements otherwise undefined return undefined which just basically is empty like don't give me anything don't give me a list item don't give me anything I just don't want nothing so I could write this entire all that if statement and functionality I can refactor it to just this one line of code to execute okay give it a little tabs e so you can read it does my refactor break anything No yeh so that's kind of the beauty of having these tests in place ahead of time right is that we can we can write out our logic to be this typical complexity to reason it out how can we make this thing work and then the refactor phase you're going in and saying okay how can I make it work better how can I react to this to either dry principle solid principles or some other set of best practices that you like for me personally as much as I possibly can I want my functions to be doing one thing as much as pod would obviously it doesn't always happen it can't always be that way but as much as I possibly can I want it to do that I want it to be one line of code execution okay so moving on obviously our tests can't do that right our tests have all sorts of different logic in it and there is actually a way I could write every one of these tests that we wrote I could do it in one line I just don't want to do that to you guys it would be a mess to try to read it's not as it might be good for implement for implementing in any code base but it's not always a hard and fast rule that you have to always stick to especially if you want people to come back and read it later this is probably a little bit easier for somebody to read a test then what I would do which would be let me just give you guys a little taste of what I'm talking about here I could rewrite this this way expect people it's not going to be people list items it's gonna be off of the okay so the way that works is this is just kind of a general rule if I have a variable if I have a variable but it's only being used once I don't need the variable okay so how many times do I use this people Const once I use it right there so rather than using the people variable I can just say okay that's just an empty array that means I can get rid of this people cost okay next up I have person list rapper where do I use person list rapper only once so instead of having this variable personal list rapper I could take this shallow and replace it for where my variable is right okay now I have just this people list items how many times do I use that I use it once we get rid of that expect you said only once so if that's the case the implementation of that variable I can just replace the variable call with the actual implementation and now that exact same test reads like this would that be easy for you to read as far as implementation no so typically when I'm writing my tests I write them very verbose ly but when I'm writing my implementation I'm writing things very very closely right I have kind of the opposite when I'm writing my tests I want full documentation when I'm writing my implementation I want as skinny as I can get it especially with JavaScript because of the way that you know we're transmitting these files across the internet you need them to be as small as possible so I try to write my code as small as I possibly can so it's just kind of when I'm writing my test I like the complexity or I like to expand it out and be as verbose as I possibly can but then when I'm writing my actual implementation I like to make things as small as I possibly can okay so uh yeah let's let's that's that would just be a terrible I I wouldn't want anybody to have to try to read that test that just wouldn't even though I know what it does it's like what are you huh to have expect shallow person list people find Li to have length zero that doesn't read at all properly so okay let's bring all of this back and let's just double check my tests to make sure everything's still passing yes it is okay so yeah this is another good one that's another kind of good little best practice I think is try to make your your tests because your tests become your use cases so if people want to know how to use your code they'll know looking at the tests with verbosity it becomes documentation so you need that Robo City but when it comes to the actual implementation of the code I try to write it as small as I possibly can as many one-liners as I possibly can because it's gonna shrink down how much code is transmitted across the wire okay so now I need to refactor this going back to our we have one person Alan Turing let's give this a similar name so renders one li elements when one person exists so there we've got our Z and we've got our O now we have to tackle em multiple what happens when there are many people so I'm gonna go ahead and copy this we're gonna say it again I don't have a great name for it yet because I don't have the code written [Music] by the way if you guys have any questions along the way please feel free to ask them in the comment in the live live chat and I'll be happy to tackle them ok so rather than Alan Turing all by his lonesome let's add I'm gonna change some people here I'm just gonna copy this in so I don't have to type it all out doo doo but there's gonna be multiple people will say Jane Curtin and Chevy Chase people are still being passed along there are two people therefore I should have two let's get rid of that extra there we go ok so now we've got our next test written let's take a look at it and of course it's failing although that's not the reason it should fail let me run this again alright there we go so to have length two so we expect a length of two received length of zero [Music] mmm-hmm how did I get zero you may be wondering well let's take a quick look at our code again well we said length of one should display a list item but we only have one list item we've got to do something now to handle this multiple case scenario we're gonna do something to allow for this to be extended so basically this isn't gonna work it's close but it's not quite going to work what I need to do is I need to take that people and instead of checking for a length of one I'm going to just do a map method on it so it looks like this yes on the map method we can so the map method for those of you are not familiar with it it's called a transform you take your array of people and you can create a new array of something so I want to take this array of objects that are first and last name of people and I want to convert it into a list item with those first and last or I just need to create a list items so what I'm gonna do here is with the map the map method is what we call a higher-order function which it takes in a function okay so this map method receives a function and that function will be performed once for every element inside of the array so I'm gonna say each so this function I'm gonna define an arrow syntax function okay of something this arrow syntax function the first parameter of it is the element that is currently being inspected so I understand this map method is gonna call this function this arrow syntax function that I'm passing in it's going to call it once for every single element in people so the first thing that it receives is that element as a parameter to the function so I'm gonna say person okay so for every person actually I don't even need person I don't even need that at all I could just say run this function I want you to return a list item I could do parameters but I don't even need parameters this is the simplest possible implementation this is the smallest amount of code I can possibly write that's going to it's not yet going to pass I think it's because just due to in a minute you have length 1 so I've got a couple of failing ones though the one is not passing why are we not passing personalist to have like the - hmm did I goof up something oh I forgot the return statement which I don't need because the zero syntax that's why okay I put the curly braces in there it's kind of a placeholder but if I do this now we should be yeah there we go but we have an error here so we're passing tests but we see a console error and that is each child in a list should have a unique key prop so we're technically passing the test but we are getting a comply cat rands filing warning so we need to fix this by adding a key to the list item element the simplest way I could try to do some sort of math.random here but really the simplest way is to just drop in a couple of parameters here and then take that second parameter which is the index and say the index so okay let me go back to what the map method is doing the map method is once again going to call this function right here this arrow syntax function it's going to call it once for every element inside of my people array right I think most JavaScript developers already know this one but just for everybody who doesn't know I'm just trying to explain the first parameter of this function which is person is going to be the that element one at a time right this function is being called once for every element inside of the array each element is going to be passed in as this first parameter so for each person I'm going to assign that person to this person parameter this second variable which not everybody knows about react developers know about this but not everybody knows about this you have a second parameter for map it is the index 0 1 2 3 4 5 etc it's the index of the current element that is being that the function is being called with so I can receive that index as a unique value that I can then set as the key because react requires this he keep prop I don't know if they call it ki what did they what it was the air well that's all passing now but it requires this key to be on a list item element if you're gonna have things that are being iterated okay so I need this key that key needs to be unique once for each element that's being generated and so we could just use the I which is the indexer of the current element in the array that's gonna be unique right 0 1 2 3 4 once for every single element that it's going to be different so we just drop that in as the key and there you go and that's how we are able to now have all of our tests passing because now for every instance if I have 0 don't create any out li elements okay because if if there's no elements in the array there's no allies to produce if I have one element then create one Li 5 two elements create your five two people create two allies etc so we're passing and you may be going okay but Steve there's no like actual things being legit tell Li elements you don't have any names or anything well tackle that in just a moment we need a use case for that all we were really saying is I need a new list item for every person so now we have that okay um next up we need to do okay so we got our person list to do what was my next thing here uh there multiple ah yes refactoring yes weird so we made it pass but we have some refactoring and probably do the one refactoring that I want to do is I really don't like the fact that we're doing this check to see if people exists on props so instead what I'm gonna do is one of the cool things that you can do is you can set a default value for a parameter so up here in my props I can set a default value for people but I need to what I want to do is I want to I want to instead of getting all of the props I'm going to I'm going to D structure the people out of props so the way you do that is you just simply wrap up in curly braces and then you name the property on here people now this is exactly the same thing we're doing up here for shallow out of enzyme we are D structuring the shallow property from the enzyme library or the enzyme class or the enzyme module whatever it is that's back there we are D structuring shallow from out of enzyme so that we can have it this is exactly the same thing we are doing right here we are D structuring the people property from the props we're passing in props but we can take a particular property on those props and say I want to make I just want to define that people as something okay as something in that I can use in my code that's exactly the same thing we did there so whenever you see this syntax just know that's what's going on you are D structuring we call it D structuring in JavaScript you're taking about one element that one thing that one property and you are bringing it in as this thing right and and you'd that way you don't have to bring in the whole thing you don't to bring in all of it you don't have to bring in the whole library you're just bringing that one piece of the library okay it's the same thing here instead of bringing in the whole props I'm just gonna bring in that one little piece called people now that means that I don't need props anymore you drop that and I could drop that but the other cool thing that we can do is we can set a default value for people so right now we've been checking to see if people exist because it's always been possible that there's no array being passed at all what if what if person list is being called but no people prop is being set at all that's why we have this okay so but what we can do is in our parameters we can set a default empty array so that if there are no people being passive if nothing is being passed for the people prop set it to an empty array and if it's an empty array we don't need to do this check anymore now we can just simply say iterate over my or map over my people array it's either gonna be empty or it's gonna be full either way it's gonna still generate the Allies and if we take a look at our test suite everything passes cool all right so these are the kind of cool reef actors that you can do because I have tests in place if I didn't have these tests already in place how would I know this is working how would I know that my refactor that I just did how would I know that that's didn't break something but because I've done all of my tests ahead of time I know that nothing is broken because of this refactor okay all my test cases the test cases of where I have no nothing being passed it to the person test component where there's no props at all that's being tested I have the one where there is something being passed but an empty array that's being tested I have one where there's one person being passed in for that props that's being tested and I also have the many now right I have two or more people and that's allowing me to do this map method so that's how I essentially the the testing has driven out the development the design of this thing okay we're approaching two hours so I'm gonna I'm not going to continue much further I just want to get to the point where we're starting to actually list the names so let's do so now that I have these list elements one for each person that gets passed in now what I need to do is make sure that the people are actually getting displayed in the list item elements so I'm going to write a new test here Oh actually before I do that I need to do this so it renders one Li element for each person that exists okay that refactor shouldn't have done anything I mean we're still green all across the board okay it all right we we know that we want it to display people names so I'm going to add an add a test that's going to check so let's go ahead and do this kind of thing again and did you do so I'm gonna do just one person here to do this test I'm gonna say when I pass in one person yes finally we'll stick with Jane what I want to do is now take a look inside of those li elements and make sure which there should only be one right cuz we're only passing on one person and I want to check to see that the names are appearing inside of the list item elements by the way let's just double check make sure all my tests are still passing yes they are okay so none of none of my tests that I've written so far have broken anything so I need to expect that the list item elements you know what let me go get those list item that list item element person list item we're gonna say is off of person list rapper and we're going to find of course the Li elements and let's do so I want to expect that the person list items let's go for zero dot text so I'm looking at the text of that item and I know that I want it to have to contain person that person's name so we're gonna new people zero first name okay so that's essentially what we're looking for we're looking for the text to be first name and in fact why don't I go ahead and throw on an expectation and this is sacrilege in some people's circles and I kind of hate doing this but having multiple assertions inside of one test is kind of kind of a no-no there's different schools of thought on this I prefer again adhering the single responsibility principle I prefer one assertion per test however I fully admit that sometimes it can be overkill and in this case we're really just checking to see if the name the first and last name is being displayed so I can understand why somebody would argue that it's perfectly acceptable to have an assertion of two things because we're really checking for both things to be true for this one test okay my personal preference would be to actually move this into two separate tests but that's just kind of my draw but I'm perfectly fine having multiple assertions if it makes sense to do so because this is really still this could be this could be argued that this is still the same thing that we're testing that it is still adhering to the single responsibility because first and last name are really kind of you know we're just testing the name in general okay better label that last name so we're looking for both of these two things and of course if we take a look at our tests it's not passing read property text of undefined um what did I goof up there what did I goof up here let me do this I'm gonna I think I need to do it this way there's only gonna be one element I think there's only everyone so it's gonna do that that's the way I originally wrote it I'm not sure why I'd have to go back and double-check exactly why that codes not working but essentially this this should work yeah that should work so now my test fails because two contained yeah that's that's where it should be failing is it to contain its expecting substring gene or yeah substring of gene but it's receiving empty so let's figure out what's going on there how can we solve this well the simplest solution is the one that we want we can go into person list and all we have to do is well we're already getting the person from inside of the you know from from each of the people the people array we're already getting a person one at a time so we can inside of our list item element just simply add person dot first name and person last name and of course if we go check our tests now everything passes okay so we're allowing the again the tests themselves to drive the design right is there any sort of refactoring yes I want to probably say something like it renders the first and last name of a person there we go so that's gonna be that's probably all we should do there's third I have more to this like adding edit buttons and adding an edit screen component but I think you guys can see we've worked through a pretty sufficient example as much that we possibly can you know and now it's time to kind of turn over to another component and adding it edit buttons but we've really driven out the design of this application using tests so just to kind of wrap this up and and put it in a conclusion box I want to go back to this slides because the three practices that we that we need to be remembering to implement here first and foremost is the obvious one run of TDD where you first write a failing test then you write just enough code to make the test pass and then you go back and you refactor and during the refactor phases where you're looking at things like solid principles or dry principles and and you want to do that with your tests too right we saw early on I was willing to delete tests that were no longer relevant right if I was if it's a test that's no longer applicable delete it don't let it just sit there and rot but be careful though be careful that you know which tests you want to that are actually not testing anything you know those tests that are not testing anything you should definitely get rid of but in general you want to keep as many of those tests that makes sense to keep right and don't just if it's covering one of those zombie cases zero and ends ami kick cases null zero one or many obviously you want to try to keep those those test cases around you let the tests drive the way that you do things and when you're doing the test that's when you're thinking about what you need to do next right when you're thinking about what is the next test I need to write that's the white board that's the design part of things that's when you're thinking about things through okay that's why they call it a white board is when you're designing the test you're really thinking about how do I want to shape this application you don't do it in the implementation code you do it during the test time and I hope that you guys can see while we were going through this exercise that that's really kind of what we were doing is we were we were figuring out what the next thing to do was based upon okay what do we want the system to do now what is the next thing that we want it to be able to do and and so hopefully you got a little bit of that obviously I have a little cheat sheet with me so I was kind of looking at that going okay well we did what do we need to do next but I think that you guys can see that there's a flow that you go through and in zombies is a good way of doing that so anyway going back to TDD look up this red green refactor cycle that we're constantly doing we do it over and over again it should only take you know I'm sitting here explaining everything as I'm going along so obviously it takes me a little bit longer to do each one of these cycles but in practice this should probably only take you maybe 30 seconds unless it's a really complex problem but yeah basically it should only you do it in these small little iterations like this it's only gonna take you 15 30 seconds each time so it seems like a lot one of the before I end this dream though there is one thing that I really really wanted to say during this stream aside for him thank you everybody for watching I really appreciate it I hope you guys enjoyed it there was a classical argument that goes on about whether or not TDD is a good practice and you'll find there's a lot of detractors and that's fine the the what I typically go through is I say okay first and foremost can we agree on this we want our applications to work okay if you and I can agree that we want our applications to work great now let's go to the next thing what is the best way to ensure that the system is working is that through manual testing or is that through automated testing I think the likely and most responsible answer most intellectually honest answer is automated testing we need some sort of automated testing that's why all let's that's why we have a QA department pretty much in general like that's why QA exists is to is because we do a lot of this manual testing instead when we should be doing automated testing and we prefer automated testing and sometimes the QA role turns into how can we write more tests how can we do better testing that's really what QA should be about is how can we do better testing keep track keeping track of bugs that are coming in and then figuring out what type of tests need to be written around those bugs that's what QA should be doing oftentimes what they're relegated to do is make sure that if I click on a button it runs which there's automated testing frameworks around that so we should be doing the automated testing so I think we all agree I think we should all agree that I don't think it's very difficult to make the logical conclusion that the best way to ensure that a system is up and working is by having an automated test suite okay now the third thing is once you and I can agree that the application should be working and that the best way to ensure that is that it we have automated testing around it then my only question is when do you write those tests that's the only thing in question here is when do you write the tests before or after you write the code before or after the implementation so in my opinion I'm a better developer and I have a more complete suite of tests if I do my tests first because I know there isn't a single line of code in my production code that hasn't been fully tested before I even wrote it there's not a single line of the code that we wrote today that isn't fully tested there are some stuff that comes out of the box that presumably somebody else already has tested but every line of code that we wrote today was tested except for the test themselves I guess you could say but even those tests were essentially tested by whoever created frameworks right so I mean there's nothing that I wrote in production that wasn't fully tested before it was even written I let the tests drive out the design and the code so tell me would you like that level of security and comfort in the code that you write that there is always a test backing up every line of code or would you rather write your tests afterwards and hope and pray that you completed all of the tests that were necessary and not only that but I think that this is a much more fun and enjoyable way of writing tests because I don't know about you but when I go and I write tests after the production code it feels like man I already know this works why am i writing tests so we tend to get really lazy while we're writing those tests right we tend to kind of go hi it already works I don't really need to do a complete testing I don't really need to completely test this system it's already working ok well that type of attitude and behavior is exactly what causes brittle code and it's so to me it's an obvious practice to take on because if you write your tests we already know first of all we know that we want a working application we know that the best way to do that is by writing these automated tests and now we know that if we write the tests ahead of time we have a much less of a likelihood that we're gonna miss a test right it's almost zero like the percentage of chance of me forgetting to write a proper test is pretty much nothing because I have to write a test first before I write the application code so in my opinion there is no reason why you shouldn't be doing TDD there just isn't unless you essentially and what it kind of breaks down to and I hate to be blunt about this but unless you don't really care about the quality of your code if you don't care about the quality of your code then fine do whatever you don't have to do TDD I do it because I believe that this is the best way if you've got a better way by all means I'm willing to hear it this is the best way that we have been able to come up with us as a body of people I mean there's there's people all over the place that they're coming up with different ways to do things and you're telling me that after all this time somebody hasn't come up with a better way than this so this is what I think we should be doing in order to have the best code that we could possibly write and ensuring that the system works right so that's something I just want to talk about it TVD in general the other two things are the three laws of TDD again this just kind of these laws really help you narrow your focus of what you're writing and really kind of add some constraints around how you write your code right so TDD is the practice the
Info
Channel: Programming Made EZ
Views: 13,349
Rating: 4.9224138 out of 5
Keywords: test driven development, test driven development javascript, test driven development react, test driven development tutorial, react testing library, web development, unit testing, javascript testing, js testing, react testing, react testing library tutorial, react js, react testing with jest and enzyme, jest framework, javascript unit testing, jest testing, integration testing, jest tutorial, javascript tutorial, unit testing react, tdd, bdd, webinar, live coding
Id: tX-gu6FWcsE
Channel Id: undefined
Length: 120min 18sec (7218 seconds)
Published: Thu May 21 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.