Episode #329

Adding XCTest to Existing Projects

Series: Testing iOS Applications

6 minutes
Published on March 9, 2018

This video is only available to subscribers. Get access to this video and 578 others.

If you did not check the box "Include Unit Tests" when first creating your project (or perhaps you want to add a separate testing target), this screencast will show the steps of how to get it set up from scratch. It also covers how to set up a scheme dedicated to building your tests, and choosing which tests to run automatically.

This episode uses Swift 4, Xcode 9.2.

Next I want to talk about adding a test to an existing project. We're going to call this testing demo two. In this case, I'm going to uncheck include unit test so we can see exactly how we set this up on our own. I'm going to hit next. We're going to create that and then we are going to add this to our project ourself. The first thing we need to do is go over to our targets. We can do that by selecting the project here and in targets area, down here at the bottom there's a plus sign here. We can hit the plus sign and this allows us to add a new target. As you can see, there's tons of different targets we can add. We need to scroll down here or you can use search and look at iOS unit testing bundle. That's the one we want. We're going to hit next and we can choose whatever name we want. I might just call this unit tests and then have another one for UI tests. If we take a look down here at the project, it's going to add it to this project so we'll have it in our projects target listing. The target to be testing, this is important to set, if we want it to actually be able to test code that exists in that target. We're going to hit finish and this creates our unit test target and it has this host application here. This host application is important so that we can actually invoke the simulator and have the simulator run so we can run our tests. Some of our tests are going to be just logic based tests in which case you might not need this, but I think it's a good idea just to leave it by default. That gives us our group here and our first unit test's test case. Typically I will just delete this one because it's not that valuable. I can go over here to the unit test's group over here and then select a new file. We can choose a unit test case class here which is going to give us some template code. I typically just start with swift file because that allows me to create it from scratch and then I know exactly how everything is set up. I'm going to do that. We'll just call this a demo test. In this case, it's asking me if I want to mix swift and objective C target and not quite sure why it's asking me that. I'm just going to say no because this is a swift project. When I'm doing my test's case class from scratch, I need to make sure I import XCTest and then call @testable import and then my testing demo two target. I believe that is the name of it with underscores when it ends up having spaces in it. Then we can create our demo tests. Inherit from XCTest case and then we've got our setup function. Remember to call super setup, that's really important as we'll see later. We've got our tear down. I typically have these in here even if I'm not going to use them because often you're going to have to use them and so it's good to just set these up by default. Then we can say test demo one XCTAssertEqual one and one. I'm going to save that. Make sure that we can run this test. Our build succeeded and now it is launching our simulator in the background and it's trying to test this and now our test succeeds. That worked because I clicked on this button, but if we're sitting over here on our application code and writing code and we want to rerun our test, typically that is done with command + U. When we run command + U, by default it's not always set up. If we go over here to edit our schemes. In fact, I'm actually surprised that it picked this up automatically. When you hit command + U, it's going to execute this test section of our scheme and if our tests aren't in here, then it's not going to work. If you notice that when you hit command + U and it doesn't actually run your tests, then we need to go over here to the test scheme over here. We need to go over to the info and add our test target. If you have multiple tests, sometimes you might have unit test, maybe you have some integration tests that take longer, maybe hit a live API, you may want to separate those into different targets so you can run them in insolation. We're going to add our test here. If we expand this, it shows the different classes and tests that are being picked up and whether we want to test those. If there's maybe a test that takes a long time or maybe this is a test you only want to run once or twice because they're exercising a real API and they take a long time or maybe they have side effects, you can uncheck them so that they don't run automatically here. There's some other stuff here that you might take a look at which is test location. If you wanted to simulate that you're in San Francisco when you run a test, you can do that. That will allow you to sort of customize how these tests are run. There's a bunch of other stuff we can check in here to see to customize the behavior of how our tests run. Another thing you might want to do is create a new scheme just for running tests. In this case, I typically do this where I'll have a unit test target only so when I hit command + B, I'm going to be building my unit tests and anything that those depend on. Now that I have my unit test target, I'm going to hit edit scheme. We're going to go over to build and we're going to make sure the unit test is in here but also our target is in there. Because our unit test is dependent on our application target, it implicitly figured this out that I need to build the testing demo two first in order to build my unit tests. Because I'm going to hit command + B, it's going to build both of these. That makes it a little bit easier for me to make a change over here that is related to a change in my application target and when I hit command + B, it hits them both. That is one thing you might do with having just a plain unit test scheme like this.