Swift: How to Migrate MVC to MVVM & Intro Unit Testing

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what is up guys welcome back to another exciting episode on the channel I hope you're doing well today now in today's video we are gonna try to do our best and discuss a somewhat more advanced topic inside of the world of iOS development and so for today's topic we are going to discuss how exactly we can transform our NBC projects into something that uses mvvm now for those of you guys that aren't super familiar with what mvvm is it basically stands for model view and view model now what exactly is the idea behind all this right well whenever you can separate your model and views into a separate review model object you can actually test your applications a lot easier now it's kind of hard to actually talk about this and make sense of it all so in today's video we are going to go through a very simple application that I have set up on the left side over there and so as you can kind of tell this application doesn't do very much it's actually just a very simple UI tableview controller and it's fetching some data from the internet using some JSON and the important part of this application is that you'll notice that all these rows here are a little bit different right some of them contain the I icon on the right side and then some of them do not the bottom text in the detail label actually contains a little bit more text on these top two rows as well so I already have this entire project built out using the MVC framework architecture and what we're going to do is we're going to look at how we can transform that and introduce some view model classes inside of our project and then finally at the very end I'm also going to show you how you can actually introduce some unit testing inside of your project as well and that way we can actually see the advantages of these view model classes all right so this video is going to be maybe a little bit more advanced so hopefully you can make it all the way to the end let's go and get started with Xcode right now alrighty guys welcome to Xcode and I hope you're ready to start diving into the right away here the first thing I would like to do is to simply walk you through some of the files that we have set up for our project over here and let's see we have a model group a view group as well as a controller group and the easiest way to walk through this is to probably look at the course model object first and so some of the properties that we have on here is let's say ID name and number of lessons you can already see some of this data being presented inside of the cell objects over here on the right side so for example the bolded text is just the course name the number of lessons is actually 32 and 19 over here for these two bottom rows and that looks pretty good alright so nothing too fancy in here and the next file we should probably move on to is the course Cell file now the course cell is actually responsible for rendering out these white rows inside of our table view and the way that we do that is basically we have a lot of styling that's being typed up inside of coats or for example text label font and also detail text label being black that's kind of why it shows up like that and let's kind of move up to the very top here which is the more important piece of code that we should sort of focus on and let's kind of see what happens whenever we set a course model object on our cell and basically here's what happens and we set the text label text to the course name so that's kind of why you see the Instagram firebase over there and this bit of logic kind of checks the number of lessons being greater than 35 okay so this is just an arbitrary number and whatever number of lessons on this model object when it's greater than 35 we set this accessory type to detail disclosure button and that enables this I icon all the way on the right side over there and so in addition to that detail label that text gets turned into lesson 30 plus and it check it out and that's kind of why you see that over there on these top two rows and all the way on the bottom right here if the number of lessons is less than 35 we actually show lessons and then we show course not number of lessons that's why you see lessons thirty-two and nineteen at the bottom okay so that is pretty straightforward and the reason why I'm showing you this is because a little bit later on I am going to show you how we can move some of this model logic into a separate view model layer okay so that's going to become a lot easier to understand a little bit later and before we actually do that why don't we go inside of courses controller to see what is going on with our UI tableview controller is subclass so that's what it is and let's see your first thing they look at is view did load so what's going on in here is we are setting up the nav bar so that allows us to customize it with this bluish color and I believe we're also setting up this large text title on the nav bar and we also set the title to be white color as well the second thing we do is we set up the table view that's kind of why we have a white for our cells and also this dark blue color at the bottom this function sets it up so that it gets customized to look like this style all right so that's not all that important and the next function that is something that we should indeed look at is called fetch data so what exactly is this function doing is a the question of the day here and basically we are fetching courses from this service layer all the way over here and this is a pretty straight for function if you're familiar with completion blocks and basically we fetch our courses we get an error back and we simply make a check there but on success what happens is on line 31 we set self dot courses which is this array of model objects all the way on the top we set that equal to the incoming courses from the completion block and then finally we just reload the entire table view with the courses that we get back all right so that's pretty good and that's typically how you would set up your MVC project hopefully you guys are more than familiar with this type of setup so with all this stuff kind of explained like that we are pretty much ready to move on to introducing our view model layer and I am going to do that by let's see first creating a group over here said this group is obviously going to be called a view model hopefully that is obvious and now the first thing we need to do is to introduce our view model file so let's just double click on that and what exactly is this well I'm going to call it course view model and just hit enter and let's see what exactly is going to reside inside of the course view model file well the course view model is going to be responsible for rendering out each of these views inside of the cells here so the way I'm going to actually type it out is to use a struct for this course view model like that and this guy is going to be very very simple it's just going to keep track of a name for now from our course object so what I mean is we're going to create this name string property and we're going to actually introduce some dependency injection via the initializer so let me just type it out first and the initializer will take in a course object like so and so this course is just simply this course model object and for the name let's call self dot name equals course dot name okay so for those of you guys that aren't familiar this is actually called let's see dependency dependency and let me spell this correctly dependency injection or I guess also known as di for short and so now that you have this view model class what exactly do you do with it right well we are simply going to go back into our courses controller file over here and we are going to modify this courses array of model objects so that instead of containing a rock course we're going to modify it to actually contain course view model all right so now this is a new array of course view model objects if you try to build you're going to get a lot of type mismatches so what I'm going to do to fix this very easily is I'm going to rename this guy because no longer makes this sense to have this guy called courses so you can refactor and a rename and it'll show you all the places to rename this in and it's actually modifying this service file which I don't really want to you so you can uncheck that and this guy we are going to call course view models with s at the end at the enter and so that looks pretty good and now what we want to do is whatever we fetched the courses from the internet via the service file we actually get the courses back but as you can see the courses variable up here is actually an array of course objects so what I want to do is I want to transform this into an array of course view model objects instead so that's actually pretty easy let me just show you the syntax here so return and it was the course view model use the initializer of course and I want to use dollar signs zero like zoom so the map function what it does is it takes an array or you call the map function on your array and whatever you do instead of here is just going to return all these objects inside of a different array all right so let me just try to type this out or cut that and what I can do is I can paste it over here and I believe this courses is an optional or race and when you have to do is you have to do this mill coalescing via this guy over here and I think that's a optional so that should hopefully work let me try to build this project and this guy is no longer that so let me just paste that in one more time and Bill so this part of the code looks okay to me now and again we're just simply transforming the courses model objects array over here into an array of course and view model objects instead alright so once you do that what you have to do is you want to modify the DQ process of cell for row and so previously all we were doing is we were saying the course object on our cell that's kind of why for the course self out this code right here that's how it was working we were simply setting the course object on here so instead of doing that I'm just going to comment out all that code and I'm going to create a new property called course view model and let's call this course view model use the forest unwrapped use dead set and now what I'm going to do is I'm just going to simply say text label dot text equals course the view model and you'll notice that the only property that exists on this object is the name property right so this actually will simplify how you perform the setup of your course of view and you don't want to include all of this logic in here because it gets really hard to test a little bit later so this is the reason why we use a course view model object it's a lot easier to read as well so the last thing you need to do is you want to go to courses controller and for the d queuing process what you can do now is if you build comment that out because they sell that course in the view model equals this object over here which is really course view models this guy's that course view model let me rename that to make a little bit more sense so command and control II can actually get to that piece of that code if I can get to it again so that's the e like that okay of course the view model just type that in and let's remove this combatant line of code build and finally we can run our project and now with the new view model layer what don't get instead of each one of your rows is simply the name for the course objects alright so that is the first step in introducing this view model layer and obviously this isn't perfect because all of the information that we had early earlier is now no longer showing instead of our cells so how exactly do we go about fixing that right so this bit of logic what I'm going to do is I'm going to somehow move this into the view model object instead so let me just copy that and I'll paste it down here somewhere so I'm not going to use that code but instead I'm just going to look at it for a reference and what I'd like to do is I'm going to create two additional properties on this view model the first one is accessory type and then the second one will probably be the detail text label so why don't I do the string one first I'm gonna say let display that display about detail text string whatever you want to call that guy let this guy be of type string as well and down here what I'm going to do is I'm going to perform the course number check inside of the initializer so if greater than 35 we are going to say detail text string equals this string over here so just paste that in there and why don't we do the else case right now and detailed text string equals this chunk of code here so the bottom else case and just paste that in there okay so that's looking pretty good to me we can go ahead and go back into our course cell and now we can build our project make sure that those properties are registered tanks a detailed text label equals course view model and you can say detail a text string so hopefully that's pretty straight for it the detail text string is just going to show up on the bottom there and so you can see that now this course cell this view object is not really aware of the course model which is a pretty good thing and all it knows about is the course view model which contains just this these two properties name and detail text string all right now the final thing is to probably include the accessory type as well inside of the course view model class so what I'm going to do now is to set the accessory type but at first I probably have to declare the accessory type above accessory type let this guy be a uitableviewcell so you see that's not available right well I'm going to import the UI kit framework inside of my view model layer and it's okay to import UI kit inside of a view class because it has to be kind of dealt with on the UI layer anyways so that's kind of fine for me UI tableview cell accessory type accessory type equals let's see what is down here we are going to use the dot detail C dot detail disclosure button and then the else case we're just going to say accessory type equals dot none which is what that is down below so now that I have all that logic type down I can just remove the comments go back to the chorus sound and you can see what I'm going to do here is accessory type equals course view model dot let's see accessory type after I build is now available so running this now we are going to get the exact same display that we had at the beginning of our application we have the accessory type as well as the text for the detail down at the bottom depending on whatever the number of lessons is okay so pretty good stuff now that we have our logic inside of course view model I can just wipe that out and now this class right here is much much easier to sort of understand the main goal of using mvvm is to make sure that your view classes are not aware of the model classes inside of your project so for example course cells should not really be aware of course it should only be aware of course view model okay so that's kind of the one rule to follow up to this point okay so that's the basic introduction into the model view viewmodel architecture and what i would like to do now is to kind of show you what the point of doing this is by introducing a unit test inside of my project and the way that you want to do this is to click on this guy over here and down at the bottom you wants to introduce a new unit test target so just click on that and down here instead of tests you have this guy called iOS unit testing bundle make sure to click that instead of the UI testing double click on that call this guy whatever you want and just hit the finish over here and that will help you create this folder which will then contain your test suite that's called this so instead of here we have the setup function we have teardown and we have two test cases that are kind of written for us what you want to do to run this is to either hit on this guy on the Left science so let me just click on that it's going to run this test for us and let's just make sure it passes all right so everything looks good and I don't see my console down there so I would like to hit the view is it navigate I see a view assistant editor book area activate console bring this guy up you have to get a lot of useful information inside of the console in regards to how your tests ran so zero failures everything passed successfully okay so that's pretty good the other option to run your tests is to go up to product and you can't see the top of my menu but inside our product we have command U and typically I just say command you to run all my tests so that's going to run this bottom test as well and you kind of see it shows up with this green checkmark right so that's how you set up a unit test target and what I would like to do is to write a special unit test case just to make sure that we can test our course model object and our course view model object alright so some of you guys are probably not really used to writing unit tests so this stuff might be a little bit foreign or it might be a little bit new to you so once you see the code it actually becomes pretty straightforward and easy to understand the first thing you need to write is a function and you want to make sure you call it test something so test X or whatever and the name I will give it as test course view model and let's just end it like that if you have this test in front of your functions it's going to actually use this as one of your test cases okay so it's actually very important to prefix it with a test and so what you can do is you can say XC assert equal and if you use 0 and 1 here it's going to try to run this test so I'm going to run it and maybe you can take a guess as to what's going to happen so it's going to run and you will see that this test actually should have failed so let's kind of see what's going on here and I'm just going to click on that and one more time it's going to launch that and there we go we have our test failure so sometimes this guy is not all that fully functional you have to run it a couple of times to get the test to work now if you click on here it says that the assertion actually failed and zero does not equal to one hopefully you guys can see why that is failing it's pretty obvious right so the next thing I would like to do is to somehow test my course view model object against my course so instead of talking about this for too long let me just create some of the code here with the course view model equals course view model so of course view model you'll notice that it doesn't show up right so the reason is because your test suite isn't actually accessing the correct files for your project so what you have do is to introduce testable and I'm going to import MVC to mvvm demo all right so you got to make sure this is called either I think it's this guy or this guy or whatever your target is over here really okay so once you import that you can start typing out some things here and you'll notice that your classes inside of your project are actually available for you to use here so wants to do that you wants to start typing out the initializer for your course view model and you have to take in some kind of course right so this is the dependency is what we call it so let's create our first dependency up here with a course and instead of equal to the course model object and this guy has a initializer that comes to us automatically set of courses over here all strokes have an initializer that you get by default so that's why you get this game the idea doesn't really matter I'm just going to give it a value of zero before the course name let's call this my course name so the next thing is to actually initialize the number of lessons so I'm going to give this value 10 and we're going to test these three or these two properties here first and so the way this is going to work is we're going to pump in the dependency with the course right there and what exactly do we want to test now right so what is it that when you want to test is the question so basically because this is my project and I know what I'm doing I'm going to test two properties here so exci assert equal I'm going to test let's the course dot name so that's this property over here it should be my course name and so if I just use an empty string over here and run this test one more time you'll be able to see the failure so I want to show you what the failure message looks like so clicking on that you see that it fails because my course name is not equal to empty string and obviously the thing that you want to test against is course view model dot name over here so you're going to assume that this is actually equal because the view that you're trying to populate with the name inside of your your cell it is actually the course view model name so these two properties should be equal and that's kind of how you first construct your initial test now the way to break this test is let's say someone like an intern or some kind of a junior developer right let's say they go into the view model over here and they modify this thing - I don't know contain something else like space like that and now that this name over here or the course view model the name is course name plus this - empty space right so if someone introduces that bug into your project what you can do is you can verify that this test should still pass but because we have that change what will happen is this test actually fails so this guy right here says that my course name is not equal to my course name with this little empty space over there okay so that's the point of having unit tests you want to make sure that all of your code is working as you expect it to so why don't we go back here and remove that bit of code hit command you that's going to run all of our test cases for us and you'll see that this guy turns into a green check with the correction inside of our code alright so obviously the next thing we want to test is number of lessons so we can say xct assert course number of lessons which is ten because we've decided to create it with ten next thing we want to do is let's see course view model and you kind of want to test the number of lessons somehow on the course view model right but that actually isn't a property of course view model and so what I mean is the actual project that you have here the view doesn't really actually access the number of lessons in any meaningful way or it doesn't keep track of it rather it actually turns it into the details string and also the accessory type so we're going to we're gonna test those two properties instead so what I mean is we're going to have to test the attribute type and also the let's see course view modeled the detail text string okay so how exactly do we test this stuff right so I guess this is the detail text string let me test the attribute type attribute type that out correctly or accessory type instead okay so the first thing that you want to do is actually construct the string that's actually inside of your course view model so what I'm going to do is I'm going to take this string over here because the number of lessons is ten in this case it's just ten I'm going to test out this so I'm just paste that in there so of course number of lessons and you know course view model details string right so let me comment that out and so if I try to run this it's going to work correctly because that's the actual string I'm expecting so let's just run that and you'll see that this still passes now the way to make it fail is well we can change the number of lessons to something large like 50 and if you try to run this now it's going to fail so let me show you what that failure message says and it is over here and so click on that you'll see that lesson 50 is not equal to lesson 30 plus check it out so whenever you change the number of lessons to something greater than 35 it's actually going to modify the course view model detail texturing property so you actually change into this style of the string so that's kind of why our test case is failing now we are going to modify this back to its head and we'll just keep it as that make sure to run your test again to verify that your test case actually passes so running that one more time this turns back into a green check mark the next last thing that I would like to test here is start equal and let's just see we are going to test the course view model dot accessory type now because I know that the number of lessons is 10 I want to test that this guy is equal to UI tableview accessory type and I believe it has to be none like so and let's see you write that one final time you'll actually get your test to pass so let's see it running running running and this still passes if you modify this guy it's to be something lot like the detail disclosure button run that again you'll notice that the test fails so it's always good to verify that the test will actually fail so that's kind of why I do this and to make this back to none if you have the accessory type to find on the second property over here you can actually get rid of this and that'll make it a little bit easier to read later on when you're looking at your tests so if you click on this guy again it'll change back to the green check mark ok so I can probably remove this and last comment over here and so that's my first test case and the second test case you should probably check for it is the the scenario where the number of lessons is greater than 35 so let me create another test case of test course view model and let's call lessons lessons over threshold is what I'll you know call this test function so this guy is a relatively similar to this test case above so let me just copy some of the the work here that sets up the actual test case scenario and the only difference is I'm going to modify this to something like 100 now whatever the course has a number of lessons a greater than 35 such as 100 some of these assertions will actually need to be changed a little bit right so what I mean is you want to check the XC TS or equal and what we will do is we're going to check the detail string first so that's good I'm going to check the detail text string and the string that we actually use here is going to be a little bit different I'm going to pull it from the view model object itself so copy that go back to the test case and for here let's just paste that in there run your test so sometimes that button doesn't appear until you actually run your test so let's click on that Run button and it'll run this test right now it should pass and there we go we get a green check mark I believe you have a test button over here as well so you can hit these little run buttons to run each single test if you want to okay so that looks good if you modify this to contain that space and run it again it'll fail and the reason is because the string will no longer match so again you can check the failure message by clicking this right X box over there so you can see this has the extra space and this guy doesn't alright so that is the test case that we actually have to write now the last assertion we have to write is to check the accessory type right so let's see XTC assertion equal and course the view model accessory type now the view model that we've constructed over here is using this detail disclosure button for whatever the number of lessons is greater than 35 so let's just use that guy click back into our assertion and over here you can just use dot and detail this closure button so again if you use none that's not going to work so let me just hit the Run button what you'll see is that this guy goes away but you'll get a failure at the bottom assertion so click on that and you'll get that the accessory type doesn't match this message right here isn't all that helpful but you know you just got to change this guy to the detail disclosure button run this guy one more time and you'll get your final test case to pass so hopefully that'll work out and there we go we have our green check mark over there okay so that's kind of how we set up our unit tests inside of our project alrighty guys today's video definitely went on for a lot longer than I had originally intended but anyhow hopefully you guys enjoyed today's a very quick intro as to how we can use the mvvm architecture pattern to make our applications a lot easier to test if you want to download these source code for today's video you can find a link down in the description below if you enjoyed today's video and if you like what I do on this channel make sure to support me by checking out a couple of the courses down below on how to build out applications using the Swift programming language that's gonna be it for me today hopefully I'll see you in the next video bye bye guys
Info
Channel: Lets Build That App
Views: 100,699
Rating: undefined out of 5
Keywords: ios, swift, development, tutorial, learn, xcode, programming, code
Id: n06RE9A_8Ks
Channel Id: undefined
Length: 33min 10sec (1990 seconds)
Published: Wed Jul 04 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.