 So I started presenting at Iowa's Death's Goat Meetup one year ago in January and I kicked off my presentation by introducing myself in Mandarin and with every other presentation I wanted to introduce myself in other official languages in Singapore. So one year ago it was like this, Ni hao, wo zia o machi, wo shi chonk, Poland. Next time I introduce myself in Bahasa. Halo, na masaya machi. Saya berasa dari Poland. And I promised that the very next time I'll introduce myself in Tamil. Which is kinda difficult. So let me try this one. Vanakam, jen peyer machi. Nan wuri, Poland kudimagen. Hello everyone, my name is Machi and I'm from Poland. And I run a blog called Switching IO. You can check it out. We write about Switch with my friends, about unit testing and iOS related stuff. And today I will be presenting about unit testing. On a daily basis I work for BBM. BBM is a messaging application. And what's great about working at BBM is the way we work. And the way we work is we use extreme programming. We do per-programming and test-driven development. So on a daily basis I do not write code on my own. I have a colleague who I work with. We have one workstation which has connected to mice and to keyboards. We solve problems together. We try to come up with the best ideas we share knowledge. And we also use test-driven development. So we write unit tests first for our source code. And then we implement the desired behavior for the application for objects. So this presentation will be about synchronous unit testing. But first, let's imagine you are working for a messaging application and you are given a task from your product manager. And you are told to load all the messages that user got when application launches. So we have this struct that represents messages that were sent to our users. Message has an author, a text, probably an identifier. And we are given this protocol called message-loader. It is just one method called load. And it has some callback that takes an array of messages. It's an argument. So this probably tells us that this is an asynchronous operation. And we have this message-loader class that confirms this protocol. It implements the load method. And for simplicity, it just invokes callback with an empty array of messages. But it's okay for us at this moment, at this stage. Let's implement this behavior we wanted to have. So we need to load all the messages when application launches. So first, let's initialize loader on the application delegate on an object that confirms this protocol. We have a loader. And we need to call load when application launches, right? So let's call load. And that's it. We can maybe print. Guess product manager didn't tell us what to do with it. It doesn't come up for some reason. That's okay. But as I told you, in BBM, first we write a unit test. Then we implement the behavior. So in test-driven development, we call this red-green refactor rhythm. First, we need to write a test that fails. Then we implement the behavior that our test tests. And then we are free to refactor when our tests are passing. So let's write tests first. Some terms for you. SVT refers to a system or a subject under test. It's good to have a common name for every test case that describes object that we currently test. Guess if you have 500 of files with tests and in every test, object under test is named differently, you get good luck with finding which object is tested. So SVT in our test refers to object under test. We can also divide the test into three phases. Arrange, Act, and Assert. So in the first phase, we just initialize our SCT. We set it in a certain state. Then we perform an action on our SCT. And after that, we can perform some assertions. Something should happen with our object and we can assert that the wanted behavior actually happened. So our behavior, load called in application, will finish launching with options. So let's create a mocked message loader that allows us to test the behavior. So let's create this class, message loader mock, NetConforced or message loader protocol. Again, we need to quickly implement a method called load. And let's call our callback with empty array of messages. And because it's a mock, it's good to test that this method was called. And we can do that by introducing some Boolean variable. And whenever our method will be called, we just set this variable to true. So state will change from false to true and we will be able to assert that this actually happened. So then we need to write our unit test. So in our interface, let's create our SCT, which is the type of UI application delegate or rather a delegate. Then we can create our mock loader. And we can replace, oops, we can replace loader on our SCT to the mock loader. And we can check here that actually a value on our loader is false. So the method wasn't called. And our action at this stage is application will finish launching with options on the SCT. But we need an application object. So let's tag our UI application short and we can use this one. So let's perform an action. Application will finish launching with options. Let's supply it with an empty dictionary of options. And now we can assert that actually this action we wanted to happen happened. So we have this test and our application sort of crashed. I'm using SCT assert macros, but test doesn't work in the same way it works in SCT subclass because it's a playground. So I can only get that an assertion took place. But this tells us that actually we need to implement the desert behavior. So we wanted to pull this load in our method. So let's do it right now. And our test should disappear. I mean the warning or error should disappear and it did. So this was TDD approach we followed. And thanks to this TDD approach we can describe behavior by writing unit test. We don't have to comment our code because tests will describe our behavior of our object. And this is actually a failsafe for changes that someone may introduce in the future to our code. But world of iOS applications is not simple because it's an asynchronous world. We usually use main thread for helping UI or changing something on the user interface. But we should dispatch heavy tasks on background threads. I can use for example dispatch queue which is a swift wrapper for ground central dispatch. And we can think of a queue as if it was a thread because every queue usually has a corresponding thread. So I'll be using these terms interchangeably. Again we have this method loader protocol which tells us that this operation will be an asynchronous operation. We also have message fetching protocol which returns an array of, and it has this fetch messages function. And it returns an array of messages. And this method declaration tells us that this will be an asynchronous operation. Not asynchronous but synchronous. So let's introduce message store object that confronts this protocol. Again we can use queue and empty array as a return value. We have our message that was introduced previously. Let's say our product manager told us that it would be nice if we welcomed our users with some welcome message. So here it is and we will use it in a moment. Let's implement message loader. It has store from which it will fetch messages. And there is our load method. Here we use dispatch queue.global and it returns, actually this call async will dispatch a work that's contained in this closure. It will dispatch it to the main thread. We will simulate heavy operations by sleeping the thread for one second. And then we will return whatever store returns to this callback. So let's write the standard unit test and let's see what happens. We write unit test by subclassing xctest case. And usually we have this SUT in every test that we initialize in setup methods. And we clean out after a test and turn down method. Let's test that at least one message is returned on load. So SUT is our message loader. We have a container for fetching messages. We perform this load method on SUT. We get some messages. So let's assign them. Let's assign fetch to messages array. And then we can assert that actually we have at least one message. Now our assertion should fail. So test this red over here. Oh, it's not surprising. It is. Good. Let's implement the behavior on message loader. So let's return here our welcome message. And this red guy here should disappear. No, it didn't. Something is wrong. Still something is wrong. What's wrong? Code run asynchronously. So we can notice that by paying attention to walks, or it fails because of the different reason. Just bear with me a moment. Good. So we make this assertion in line 200. So execution order of execution is like this. We have an assertion of the main thread. We print messages which are empty. And then we assert that it isn't empty. And clearly it fails. And maybe if I run it again, it will show us the background thread. So the callback is called asynchronously somewhere later. And only after that, our messages change. So how can we test asynchronous behaviors, asynchronous code? We need to use XC test expectation class. Then we have this stack that was presented a moment ago. So message loader, message store. And we have our tests. So how can we use XC test expectation? We just need to create an instance of XC test expectation. And it has this initializer with the description that we can use. So still our assumption is that the callback should be invoked with at least one message. So whenever a callback gets called, we can assert actually that messages contains at least one message. So let's assert message as empty equals false. And if assertion is okay, if test passes, we can fulfill our expectation. And then the last thing we need to do is we need to wait for this expectation for a certain timeout. So let's wait for just a second because we select it for one second. And our test should pass. And we can, again, see the logs, how the execution goes on the main thread. So we start our test. We have this call here main thread before wait. Then we enter our callback and the background thread. We can print our messages. And then we have this statement for... on the main thread again after the wait. So actually this wait blocks our main thread for two seconds and probably pulls if the expectation was fulfilled. Then we finish the test. So what are the drawbacks of this approach? At triple length, our inject assert is not clearly visible. This is the first drawback. The second is, of course, code runs asynchronously and we don't have full control over it. And it adds some overhead. Execution might be longer, especially if we deal with lucky tests and somebody increases the timeout. If we increase timeout for 10 seconds and we know that this test failed, we would have to... our running timeout unit test increases, basically. So unreadability. We have this assert phase, somewhat indented in the callback. It's not clearly visible. And we don't know actually how to test... how to name this phase waiting phase. It's not an assert phase. So who knows? Then we don't have full control. We don't know when the callback will be invoked. And we also don't know what the volume of the timeout should be. I've seen a dozen of timeouts of 10 seconds, 20 seconds. And the majority of times there should be less. And we have this overhead of execution. So if test is lucky, never increase timeout. Timeouts should be somewhere around 100 milliseconds. But we can do better than that. We can run our unit test synchronously. So let's do that. Again, we have the same stack of messages, loaders. And we can introduce a protocol. Let's call it dispatching. And it has this one method called dispatch. And it takes an argument, a closure of a work to dispatch on a background thread. Let's create a common superclass for other classes. It contains a dispatch queue. So every SAP class will get this initializer if it inherits from the dispatcher. And let's introduce an asynchronous dispatcher. An asynchronous dispatcher inherits from the dispatcher class. And it conforms to this dispatching protocol. By implementing this method, it executes job asynchronously on a queue, on a dispatch queue. And asynchronous dispatch means that we just put stuff to this queue and it will be invoked somewhere in the future. Or executed somewhere, sometime in the future. We can also have a synchronous dispatcher. And this time job is executed on a queue synchronously. Synchronous dispatch means the calling thread. So the thread that calls this sync method on a queue waits for execution of job dispatch to this queue. And only after it finishes, execution of program goes to line 139 and returns from the function. So our message loader changes a bit. Now we have a queue that conforms to this dispatching protocol. And this class only sees an interface. So class knows that it can call dispatch on a queue. And that's it. So we initialize this loader with a queue. And in the load method, we'll change, we just call dispatch instead of dispatch queue dot global dot async. And nothing else changed. We can also add some syntactic sugar to our async dispatcher. And sync dispatcher, we can pre-populate some let's call them queues or dispatchers. So you have access to main queue, to global queue and background queue. And we can do the same for sync dispatcher. And now the last part. In our tests, we just need to set a synchronous, sorry, asynchronous, doesn't sound good. Synchronized dispatcher. Let's call it background. And we can use global queue or background queue. And we just need to switch queues. So RSUT has this queue property. Let's use this background synchronous dispatcher. And something doesn't work. Synchronized dispatcher to the background. Oh, it's dispatched queue. It doesn't look like this. So what I wanted to do is to use background queue. Here. And it should compile. And here in ActFace, actually we don't need to do anything because this code will run synchronously. So what we need to do is just to make an assertion in the assert phase. So let's do that. Again, we want to assert messages aren't empty. And if I did everything good, it should work. As we see from the logs, we start the test. We have an arranged phase on the main thread. Then we have an ActFace on the main thread. Our callback gets called. On the background thread we print our messages here in the callback. And then we enter assert phase on the main thread. So we have full control over the execution of the unit test. What happens? Unit tests are run on the main thread. So we run our test at least one message on load function. Then it calls load on our SUT. Then our SUT dispatches job to the queue. And that was it synchronously. So we have this background thread. It performs some work in background. The main thread waits for the background thread until it finishes execution. And then the background thread calls completion block, completion closure with messages it fetched. And it's all synchronous. So this one thing we should be aware of when using this approach that work. Imagine this situation. We have this load method on message loader. But this time we want to get job done synchronously on the background thread. But we want callback to be invoked on the main thread. Similar stack as we had previously with message and all the protocols. This time our message loader would look differently. We have main queue in background queue. And initializer gets this queue gets this queue and sets them as properties. Our load method now dispatches job on the background queue but dispatches callback on the main queue. Actually I didn't say whether that will get. So in multi-threading for all the deadlock can occur whenever one thread enters a waiting state because it dispatches for example job synchronously to a different thread. And if this secondary thread tries to dispatch something synchronously to the first thread and it also enters waiting state we have a loop. Every thread waits for another thread to finish its execution but it cannot because the dispatch works synchronously to each other. We can have deadlock in our message loader when we use synchronous dispatcher on main queue. And we can also break it. So this is the image that shows the situation. So we have this synchronous dispatcher to the background thread but then background thread dispatches job synchronously to the main thread. And because main thread didn't finish previous operation and waits for this thread to finish the other cannot finish as well. So situation with no deadlock how can we break it? We need to create two queues first of them let's start with background so again we can use same dispatcher the background for that but for main queue we will instill our test run synchronously so what we need to do is just to dispatcher to switch queue queues we will use global queue as the main queue I'll use the variables and then we need to switch those queues on our SUT so we will use this global queue as our main queue and still background the background loops compiles and again the last thing we need to do is to make an assertion that our messages are open and empty and we can see from the logs that code still runs synchronously and maybe if we want it will please come around this run so we have main thread main thread then call back on a global thread and then again insertion in the main thread again we have full control of our tests and we don't have any deadlock because we used three queues the main thread on which unit tests are run then they dispatcher synchronously to a background thread which dispatch call back to another background thread so I'll take away for you asynchronous tests are unreadable can give some overhead we need to manage timeouts for them and we don't have full control over asynchronous tests synchronous tests has readable arranged arc and assert phases there is no need to increase timeout whenever a test fails and we have full control over them so that's it any questions? yeah it can be yours I remember that there is another question since you mentioned that you guys practice pair programming right so how does this unit has come to practice so the question is how much do we practice unit testing and TDD and how effective is pair programming compared to the traditional solo programming so I think the best benefit you can get benefit you can get is that we learn from each other we have different background and it's better to have two pairs of eyes at the same code because you can one person can see things that the other person does not and we don't for that reason that we use pair programming we don't top into code review process because basically pair programming is sort of a code review depending on the future or you do it after you finish depends on the future because of course TDD demands having some knowledge about the platform so if you are a very experienced developer you can just dive into writing test first and then implementing the feature if you know how to implement it in advance there are times when you just don't know and you need to play around do some spikes to implement features but the majority of times we write test first then we implement the features or whatever the task is and what it gives us is simple implementations and we can also write tests for edge cases for our source code these were two questions yeah so in the synchronous test case we ran into the possibility of deadlocking one rapidly by introducing additional queues why not go the other way since you are already blocking the main queue to do all the synchronous executions why not just run everything on the main queue and never have deadlocking maybe it doesn't matter much that could be I haven't thought about it this is why thanks what would you like to test I can get this part I created a target action method so is there a way to who you need testing on this kind of method because the return is like being returned to another function I cannot think about it at the moment but we can discuss it after the presentation I can come up with another thing at the moment any other questions so your example mock a third party service you mean the message loader yeah you can think about it how detailed are your mocks how detailed are my mocks so it's good to describe the interface remark in terms of protocol so you can conform to this protocol and implement all the methods and you don't need to have all the checks for boolean variables that method was called or wasn't it depends on which methods you use on the mock objects actually at the moment we don't have much script code we use Objective-C and we can tap into OCMock to perform some studying and checking some values and assertions because sometimes I find my mocks need tests now because they are so complicated now some mocks should be I think they shouldn't contain any logic just boolean values toggle and what else I previously wrote for example I had to describe a certification center in terms of protocol so I left empty implementations for any methods I didn't use but I was able to describe a certification center in terms of protocol and I was able to check only parts of the implementations I used any other questions so let's call it a day thank you