Search code examples
iosunit-testingxcode-ui-testingui-testing

iOS - How to differentiate UI and Unit tests, and how to use them in this concrete situation?


I am completely beginner about UI and unit tests, and very confused about how to use them, as well as how to differentiate them. So I have thought about the following use case:

I have a user who has a set of MyData, a simple object like this:

class MyData: NSObject {
    var settled: Bool?
    var id: String?
}

class User {
    var datas: Set<MyData>?
}

Here is the behaviour of the application: the user comes on a MyDataListViewController that's in a loading state first, the viewDidLoad method fires an asynchronous function, let's say we use Parse for this:

static func loadDatas(success: ((Set<Data>) -> Void)?, error: ((String) -> Void)?) {
    // Here we fetch the datas and return then in the success or an error
    // ... 
}

The callback result fills the controller's UITableView, and when tapping a cell, it opens a modal popup for the specific MyData with a button to change its settled value.

myData.settled = !myData.settled
myData.save()

Given this information,

  • How would I separate my UI and unit tests?
  • How and what should I setup for each of these tests?

Thanks for reading me and helping me out, and sorry again if this sounds very beginner. I'm still very confused about the subject. Also, sorry if a better place than SO matches for this kind of question, I really didn't know where to ask.


Solution

  • The answers to your specific questions would be far too long to put in an SO answer. However, one of your root questions seems to be what is the difference between a unit test and a UI test. That can be answered here.

    The really short version is that unit tests have access to the code in your app (or whatever kind of module you are building) and UI tests do not have access to the code.

    A unit test only tests one single class per test. Any objects that the class would need to interact with should be replaced with a fake object that the test controls. If you don't insert fake objects you have no way of knowing if a failed test is from the thing you were really trying test or something that it uses. (It should be noted that there is also such a thing as integration tests that test features without faking anything more than maybe network responses).

    Ideally for unit tests you want to have a test case class for each class in your app. Then each test case can focus on a single class and test it as throughly as possible.

    UI Tests make use of the accessibility features of Apple's various platforms to effectively pretend to be a user using the app. The idea is you use Xcode to record the series of actions to accomplish a task within your app (perhaps to add a todo item) and then edit the code Xcode generates for you to test for specific things, like does the table view now have one todo item in it and does that cell contain the right title.

    You will need to use Xcode's recording feature for UI Tests to start with as the code will look a bit foreign to you at first. This is because the UI Tests don't have access to the app's code so it can't ask for an outlet, it has to find the element with accessibility (your life will be way easier if you add accessibility labels to as many of your UI elements as possible).

    To get a more in depth look at Unit and UI Testing with Xcode there are a few blog posts and books around:

    Blog posts

    Books

    I'm sure there are other resources out there but these should get you started. The Ray Wenderlich article should get you a good overview and allow you to formulate more targeted questions for Google and SO.