UI Testing iOS Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome back to another code for a tutorial so are you tired of buggy code of your boss emailing you or calling you on a Friday night asking why something is blowing up in production are you tired of sleepless nights wondering of some solution that you implemented is gonna work under all these different scenarios and that you wish there is a magic secret formula that you could use to make all of your bugs and all of your problems go away well let me tell you a little secret there isn't one but there is UI testing and in this tutorial we are going to go over some introductory concepts of how we can use UI testing in our apps to automate a lot of the manual testing improve the stability of our apps and reduce bugs if your new iOS developer looking for a great beginners course make sure you check out my iOS beginners course available on both Skillshare and lenita me it's great for beginners you can sign up with my links down below in the description and get the question 50% off for two months of scotia premium for free also make sure to follow me on patreon I will be posting more premium content on there that will be for patrons only so let's open up Xcode and get started alright so for UI testing so we're gonna start basically with a starter project and this project is going to contain an app that looks like this it's kind of like Apple music meets Spotify and it's it's just a joke but you know so we want to basically construct the UI tests for this really simple user interface and we want to do it for the login section and here we want to find a way to basically perform some UI tests that can automate logging in for us and verifying that certain things are passing our tests right and so that's what we're going to do the code for this app has already been written and so if you head on over to my github page the code Pro /i os UI testing tutorial you'll find the repository there and you can clone it and start off with the starter project that I have rather than having to write all this code from scratch we don't want to do that just a caveat I am using the Xcode 10 GM so if you're trying to build this on Xcode 9 you may run into problems so just a heads up you may want to be on the 10 GM for this one so let's just take a look at what this app does it's really basic and everything in the code is fake it's all just mock Dalek really so you've got a couple of rows here in a static table view and they don't do anything but we have this profile button and we come in here and we can perform a login right so there obviously is a valid set of credentials that I've hard coded just for the testing purposes so if I go through an invalid login flow right and I hit login I get an error message saying you know invalid username right and there's a little spinner here and some status text and if I put in a valid login and log in again let's see what happens here and so you can see there's already some quirky things going on but now that we're logged in we have a new section available all right so we have something calling my downloads so you know maybe something that is going to be specific to a user profile that's hidden until you log in and this doesn't do anything it just adds or basically on hides a row that was hidden before okay so we need to actually add the test target to the project because right now if you go into the project which is called UI testing tutorial and you go down to the targets there's only one target here so generally when you create a project you'll be prompted to also create the unit test target and the UI test target optionally if you'd want to do that so I didn't do that and that's why we'll have to do this manually but if you hit the plus icon we can bring up our new targets and if we scroll down here to the test selection so I'm sure you've seen the unit testing bundle and you may have seen the UI testing bundle and this is also where we would add it so well we'll select here is UI testing bundle and hit next and hit finish and you can I'm going to do it in Swift but you can also pick objective-c if you choose to do so and now we have our separate target here for UI testing tutorial UI tests so if we go down here let's just take a look at what gets generated for us and you can see here that it's a very basic test case that we need to go ahead and fill in now let's kind of compare and contrast unit testing versus UI testing so you've probably heard of or have interacted with a unit testing before and that's much more granular you're testing very small pieces of your code at a unit by unit hence the name and verifying that things work under all kinds of different sets of criteria edge cases and whatnot but with UI testing we're not really caring about how to test you know our network service layer or things or components inside of it it's more blackbox it's more approaching things from the mindset of I am a user using this app I enter in my username and password and hit login and you know I wait and eventually I'm brought to the next screen of the app and I or not right it failed for various reasons and I'm stuck at the login screen with an error message so that's kind of the mindset here we're going to approach this more from an automation point of view where when we write our tests we can automate a lot of these flows we can automate a login flow success we can automate a login flow of failure and then we can kind of simulate what we want to happen we can run assertions to make sure that during certain UI components are visible when they should be or not visible when they should not be visible and so those are a lot of the things that we can control here but it's important to understand that we are not testing the low-level pieces of our code we are testing the higher-level interactions with a lot of these tests so what we'll do is construct three tests that cover a few different things just to give you an idea for how you can use this and apply these concepts in your apps all right so we can start by deleting this test example code here we're gonna just use our own and before we write our code let's just look at that login view controller real fast so you can see here that if we hit the look at the login function we do some validation on the user name and password and we set a key to true for logged in on success and basically wait for 3 seconds to simulate the loading of the login and then finally dismissed this our viewcontroller and go back to the main view controller the credentials are hard-coded and just for the sake of ease and and so that's what this login screen is expecting to get from the test so if we go back over to the UI test file what we can do here is we're gonna create a test called a test valid login success right so func test valid login success oh and one other thing you want to check out for make sure your scheme for UI your UI tests is here I added mine and it wasn't so I had to actually go to new scheme and make sure the target was the UI testing tutorial UI test so if you're having that problem you can just go here and add it manually like I did and when you do that just make sure your actual application target is selected when you are recorded and run the test so like I just said we actually record tests to capture a lot of test information so there's this little record button down here and if you hit it it's going to build your app and and run it so this is pretty interesting because now if you watch here I click profile button right and codes being automatically generated for me by the test so if we go here and we look for so we're testing valid login right so I tap into the username field I type my valid user name I type my valid password and you can see that as I type things are codes automatically being generated for me from the test and then I hit login and we wait here and we can see that the downloads cell is available and if I click on the cell you can see that it's also showing down here in the test code and so that's the execution path I want just for this test now I can go ahead and hit the stop button and so you might be thinking okay well what does all this mean and how does it work because it's all this looks like junk and kind of the way it works is the UI testing framework plugs into accessibility or the accessibility framework and it can read lots of the static text and labels and descriptions of UI elements on the screen like it's doing here and then it can infer things like static text or buttons and secure text fields and so we can query against a lot of these things to write our assertions so what this code is good but it's not really going to be valid for testing purposes so what we we want to do is set it up so that we can use it so now that we have that we can start doing stuff like this so we can start with our let valid password equals abc123 valid username equals code Pro and let me see here with our actual application so this is fine this is what kind of triggers everything and so we need to simulate the tap to get to the profile so what we can do here is we can leave this as is that's fine that just gets us to the screen we can do another thing here so we can delete the tap there and we can do a let user name text field equals app dot text fields user name and we can then do a user name text field tap one thing you got to watch out for because you can fail your UI tests on the simulator is you need to make sure that under the simulator with it selected where was oh yeah if you go under hardware and you go down to keyboard you want to make sure your toggle software keyboard is turned on because that lets your keyboard get focused like it would on a real eye are undone sending issues there commands K is what's going to do that for you and so now that we've done that so we hit the tap tap gets focus makes it become the first responder in the chain we can then do another thing like user name text field dot set there's a type type text and we will type in the valid user name so we got that part down and then we go down here and so we're doing the same thing on the password here so let's password text field equals that remove the dot tap so we can perform that action and separately here so we do password text field tap to get focus so that it becomes the first responder and we do password text field type text valid password and so so far so good now one other thing we can also do here is you know how do we make assertions how do we make sure that something is visible so there on all of these elements there is a dot exists property which means that the element is visible so along the way we can start adding assertions we can assert true that the password text field exists if it doesn't if it's hidden something goes wrong will fail the test right here so we can start baking in lots of those little things along the way we can do the same thing for the username field so xct assert true username text field that exists and if we fail then you know we'll catch it there as well so we're good there we got focus we added in the password now we've got the login button dot tap and at this point it's going to do the login and it's going to go back to the other screen now let's try something let's try this as is so what I want to do is I don't need a tap on the downloads because I just need it to get access to the name of it so let downloads cell equals that and let's do some XE t-true downloads cell dot exists okay now let's run this real fast and see what we get alright so my test is running let's see what we got so something failed uh-oh so let's see what's going on here XE t true so true failed so why did it fail well it may be something to do with the timing of when the login screen is dismissed because you notice this happens right away but in reality what's happening in the login screen here is there is a slight delay of three seconds before it stops animating this and dismisses so how do we account for that well it's really not that complicated what we can do is we can create in an expectation for that so right before we do that assertion let's do something here we'll do expectation and you can see that there's one that takes in a predicate and evaluate something and has a handler so that's the one we're going to use and for the predicate what we want to do is create a predicate that looks like this it's predicate so we can do one for exists equals one and we can evaluate something and the something is going to be in this case download cell and for the handler I'm not going to use it so I'm just going to pass in nil and then right below that we're going to do a wait for expectations with a timeout now I'm going to give this five seconds just to be safe because there was a three-second delay and you know I don't want to do it too close work it fail and for my handler here I will also use nil pass and nil and let's go ahead and run this again with the expectation there that's doing the assertion for us and so you can see that that test just succeeded right so it needed a little bit of time there to actually dismiss the screen and assert that that cell is visible now and so in real life testing that just may be something you have to deal with right maybe your web services take some time you need to you know give it a little bit of time to respond you know and if it fails completely then you know okay there may be something going on that's wrong right so so that's our success test now let's go ahead and test one of the invalid login credentials cases all right so our next test is going to be a little bit simpler so what we'll do is create another one so func test invalid login missing credentials alert is shown so that's the expected outcome for testing our invalid login is we should see that pop up now let's start recording the test so it's real simple we'll end up going to profile and just hitting maybe just doing something and hitting login and we've got this missing credentials missing username or password and that's it so now you can see that we've generated some code here in our test let's see if we can clean this up so that we can run our assertions against it so we've got our app we have the way to get in here now we're tapping on user name we're tapping on login and let's see here so this is where we can break it up so let's say we wanted we want to let the alert dialogue equals that I'm just gonna take the buttons off here and we'll do it an X et assert true on alert dialog dot exists and after the assertion what we can do is call alert dialog type buttons that okay dot tap if we want to to dismiss that and then that can be our test so it can be that simple now let's run it again and so our test passes now if you want to test your test and make sure that what you're actually doing makes sense what you can do is if we go over to login view controller and we go down to the presents alert method let's just comment out everything in here go back to the test so let's just say someone makes a change to the project right like someone changes how the alert handling is implemented but never updates the test so then you go to run your test before you make a release of the app and you know you're gonna basically fail this assertion because now you're no longer showing an alert but you still have a code here that is trying to execute that path and so you can see my test just failed because I doesn't exist it's commented out and it was never shown so that's just one way you can kind of sanity test your tests now we've got one more test two right here so go ahead and do a func test invalid login progress spinner is hidden now actually I know that this behavior doesn't work that way it actually shows so there's already a bug in the code here intentionally to show us how we can correct it and use the test basically to kind of identify problems in our in our actual app code and so let's just start with our constants here I'm just going to copy our credentials from the other test and paste those back up top I do need an invalid one so I'm just going to do invalid password because I need to simulate the invalid path and now at this point I can start recording so let's record this test and so we go to profile and we go hit login and okay to dismiss and so this thing is still spinning it shouldn't be spending we don't want it to spend but how do I access it in in here right because you know it's not something I interact with so you can actually click on these elements and because of how the UI testing framework plugs into accessibility it can find it so it found app that activity indicators in progress tap so we can use this to basically query and assert that it exists or it is hidden there things like that so really we have everything we need now to construct our our test here so let's go ahead and just dismiss this and stop recording and start writing our test logic okay so we actually don't need this one here I think I tapped something else in the screen that generated that we just need everything up to this point so let's take a look what's going on here we have our let's see our application you know actually I don't even need my I just realize I don't even need these so that's fine so we'd have our login button here and we have our missing credentials so we can do here is let alert actually no it's fine we dismiss it and what we really want to do here is check this so the in progress spinner so let's activity indicator view equals app dot activity indicators in progress and we don't want to tap it I just use the tap so that the test could generate it for me so I could figure out what it was called which is this here now what we really wanted to do is not to be present right so what I can do here is xct assert activity indicator view dot yeah see here exists things he actually know boss right and I don't need these here now in order to actually fix that what I need to do is go back into the login view control because if I run this code right now it's still gonna fail I haven't actually made an implementation change to hide that so if we go back into our login view controller here let's see how we can fix that so login says start animating for the spinner and we go through these checks here where we present the alert now we never call stop animating at any point so it's still spinning and we only call stop animating on a successful login so if we want to fix that we can do really one of two things we can put it inside of every guard check before we present the alert or we could put it in the the present alert itself so let me just for the sake of simplicity I will put it there even though it should probably be present error instead of alert so it makes more sense to stop it in this context but that's okay so stop animating right and actually if you scroll up here I have a hides when stopped property set to true on the loading activity indicator so that is one other caveat to consider here let's go ahead and run the test ok and you can see that test succeeded because when I call stop animating it will automatically hide the activity indicator which would then pass the exists check and so that pretty much wraps everything up for this tutorial one other thing I wanted to touch on is there is this continued after failure property that's a faults just like the comment says it's usually best to stop immediately when a failure occurs so you could set that to true if you want to but if you want to let the you know tests continue to flow after a failure you can do that and just look at the test logs at the end and see what passed and failed now if you want to run everything all at once and automate the entire flow you can go up to the class level and hit the play icon here and then that's going to run all three of our tests so now this is really great because now we can automate a lot of manual testing that we may have had to do ourselves right so you know let's say we're making really big changes to the app we're refactoring things and changing the underlying implementation of things well if we have a suite of tests on hands like this ready to go that can test a lot of these paths then we can save ourselves and even QA people a lot of time because these can already be scripted ready to go and they test existing flows and all you have to do is play them you know run them all and see what happens when you make big changes underneath the hood and so that that saves a lot of time catches a lot of bugs and development and it's really valuable to consider adding these in a long your development flow so maybe you finish a view controller and in addition to your unit tests you start creating the UI tests to hit the high-level overview of things like inputs and expected transitions and all the all the things that are kind of at that level and that wraps up this tutorial so hopefully now you have more tools in your toolbox that you can use as you develop your apps now that you have UI testing at your disposal you can automate a lot of that manual testing flow it'll save you time and money your company time and money testers time and money so it's really valuable and you can cover pretty much your entire app using these techniques and really catch things in the beginning hopefully before they go out to production so if you like this tutorial you know what to do smash that like button make sure you subscribe to co-occur to stay up to date for all the latest tutorials also make sure to follow me on social media you can find me on Facebook on Twitter and on patreon and if you follow me on patreon I will be posting more premium content on there coming up soon for patreon supporters only so make sure you check that out so let me know in the comment section down below what tutorial guys like see you next and thank you so much for stopping by I will catch you in the next one you [Music]
Info
Channel: Code Pro
Views: 35,885
Rating: undefined out of 5
Keywords: ui testing ios, ui testing ios swift, ui testing, ui testing in xcode, ui testing swift, ui testing tutorial, ui testing xcode, ui testing xcode tutorial, beginning ios unit and ui testing, ios ui testing, ios ui testing tutorial, ios unit testing and ui testing tutorial, xcode ui testing, xcode ui testing tutorial, ios unit testing, unit testing, unit testing video tutorial, user interface testing, xcode testing, xcode unit testing, code pro tutorial, codepro tutorial
Id: rmKbsQ41wVY
Channel Id: undefined
Length: 26min 59sec (1619 seconds)
Published: Sun Sep 16 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.