Following up from my presentation at CocoaHeads last week, I heard some feedback on my proposed iOS Testing Pyramid. Specifically, Andres Catalan challenged my removal of the service layer. He told me that he felt like I underplayed its importance. Removing it as something worth of dedicated testing meant that you’re missing out at a key way to add quality to your application. I think he made a good point, and I wanted to acknowledge it here.
The Service Layer’s API is Important
Tools like CocoaPods and Carthage (and soon the Swift Package Manager) make it so easy to include third party code with your apps. I’ve taken advantage of these to great result, they’ve certainly brought so much to my apps. Despite whether you use a dedicated package manager, or manually add the code to your project, the thing is, you are adding someone else’s code to your project. This code is subject to change, and certainly contains bugs (regardless of whether you’ve found them or not).
The question is, should you, as a consumer of the third party code, write tests for this code that you’re consuming? Often, this code that you’re consuming “as a service” connects with crucial parts of your application. Personally, I’ve gotten great use of SSKeychain as a wrapper on the keychain. The keychain stores secure data, so it’s hard to think of something more critical than that! Making sure that this third part service works as advertised is of fundamental importance to my app working, AND the security of my users. So the question presents itself, how should consumption of code like this be tested?
Testing the Service Layer
It’s no secret from my prior article on the iOS Testing Pyramid that I don’t actually advocate testing the Service Layer. If I did HAVE to test it, here’s what I would consider:
- What should be tested?
- When should it be tested?
- Who should be testing it?
What Should Be tested?
If you, the consumer, do decide to test the service layer, there’s two things I advocate when considering “what should be tested?” Only the API that you are using should be tested, and only test from the outside-in, even if you have the source. For example, using SSKeychain, there are several different methods available for storing and retrieving data in the keychain. I only ended up using a subset of those in my application. If I were to write dedicated for my use of this “service layer” then I wouldn’t write tests for anything beyond the methods that I was actually using. In other words, you don’t need to write comprehensive tests for every publicly available API method for the third party library. And furthermore, when writing tests, consider your perspective as a consumer. Often, dependency tools like CocoaPods include dependencies from open source projects where the full source code is available. Despite having access to the full source code, DON’T TEST IT! Stick with the public APIs.
When Should It Be Tested?
I like to main strict manual control of the third party code that I integrate with my applications. As a result, I specify exact versions of CocoaPods and Carthage dependencies in my code, while also checking in the third party code into my repositories. Don’t forget how one programmer broke the internet by deleting a piece of code from his NPM package. I absolutely advocate maintaining a local copy of the third party code that you use, so that if it disappears from the public repository, you aren’t dead in the water looking for your third party dependency. When considering, “when this should be tested?” I put all of this into consideration. How frequently will the code change? How frequently will by use of the third party code change? To sum it up, if I ever upgrade versions of the third party code, or if I change my use of the third party API, specific consideration for testing must be made in order to maintain high quality of code.
Who Should Be Testing It?
Well, this is the million dollar question (not really). The long story short, in my opinion, is that the original author should be testing their code, and including those tests with their open source code repository. Assuming that the project is open source, it’s easy enough to see if the tests were included. This isn’t always the case. I can’t tell you the number of times that I’m browsing from open source project to project, and there are zero automated tests included. If that’s the case, you absolutely should consider writing these tests yourself through your own consumption of the API.
To Test Or Not To Test?
At the end of the day, if I do find myself writing tests for the service layer, more often than not those tests are going to be bundled with my other tests – the unit and UI tests. They won’t be dedicated tests for the third party code. And I’ll rely on design patterns like Adapter to encapsulate the third party code into a closed off portion of my own code base so it can be swapped out down the road if needed. I hope I gave you some useful things to consider in your efforts for deciding whether testing the iOS service layer in your iOS apps is worth it.
Happy cleaning.