The results of my reader survey are in. The #1 request? Case studies of unit testing, with more complex examples. And that got me thinking about the next major direction to take this blog.
When I was first learning test-driven development (TDD), I didn’t really have any examples to look at. All I had were descriptions of TDD. I stubbornly believed that these descriptions showed a more effective way of programming, so I fought my way there through the School of Hard Knocks.
But you shouldn’t have to do the same.
Over 250 of you responded to the reader survey — thank you so much! The data I gathered is very helpful. I learned that most Quality Coding readers face two frustrations with unit testing: “I don’t know how,” and “There’s not enough time.” I think these are actually related, because not knowing how to do something certainly increases the time it takes. And the #1 request from the survey was for “more complex examples.” You want examples that go deeper than just incrementing & decrementing a counter. It’s kind of like I showed you how rack-and-pinion steering works, then said, “Now, go build a car.” That’s a big leap.
So, let’s build a car! …Or rather, an app. In the coming months, I want to work through a complete case study of how I would build an app, with you looking on. I want to show you that by applying certain practices, every iOS developer can create code that is clear, robust and testable.
Benefits of a Case Study
- Depth: As we work through various parts of iOS technology, we’ll touch upon many details.
- Breadth: We’ll address a number of topics other than TDD. These include unit testing, design, tools, and language issues.
- You’ll get to see when I use TDD, and when I don’t.
- Design Issues: Clear code doesn’t happen by slapping tests onto code. It raises many interesting design questions—from choosing good names, to what architecture is for.
I do want to add some disclaimers:
- It’ll take time. I don’t want to rush through this, because there will be many details I want to discuss.
- The design won’t be perfect. But that’s okay! We’ll change things as we go. Part of this whole example isn’t just the “finished” code, but the process of getting there.
- I’ll make outright errors. There are parts of iOS I’m not familiar with. I’m counting on you to help steer me straight!
Let’s Do This
In his book Test-Driven iOS Development, Graham Lee spends most of his time on a single case study, a Stack Overflow browser. I want to do something similar. You’ll get to see practical approaches that you can put to work. I think it will be a lot of fun.
So: What kind of app shall we build? Leave a comment below with your ideas & suggestions!
Update: Everyone wants the app to network to some API. But which one? Be as specific as you can. :)
How about a test driven app that uses audio and photos?
It should have networking. Consuming some online API.
Indeed, writing tests for something that consumes a web-api is never covered by any tutorial.
This one gets my vote too
Definitely. Any suggestions for a particular API?
Maybe the flickr API? https://www.flickr.com/services/api/
It’s well documented, you can authenticate, perform searches, send information to save… I think it is a pretty complete API and also covers Rob Brennan request of a photo app.
Would be nice if we also integrate async web service calls – for me it is always the hardest thing with TDD/BDD
A business application that consumes an API and then a form that collects data and stores within core data.
It’s imperative that it covers async operations. Network requests should be a must. Also, TDDing UI doesn’t seem to have many cool examples and it would be great to have some.
But the tricky part to test is important intermediate states:
Not just asynch network i/o, but i/o with a progress meter, and where the server someties sends errors or bad data.
Not just UI, but UI where the objects change shape as they move along a path:
I agree with the others that TDD async operations and UI would be a good idea. TDD async operations would require a mock object which is good because that’s another area that is never really covered beyond trivial examples.
Another area that would be nice would be to cover functional or acceptance testing. Too often TDD is seen as synonymous with unit testing. A proper TDD project includes unit tests, functional tests, and continuous integration (to automatically run the tests and report failures when code is submitted to the repository).
Great idea, Jon!
In addition to network it also would be good that the app uses CoreData, schedules local notifications and asks user permissions for different things (audio, contacts, photos and so on). Also would be nice if it is a Universal app for both iPhone and iPad so some views or controllers may look differently.
Would be nice to have the app on GitHub, so we, your readers, can also propose some pull requests :)
Everyone wants a networked API. But which one? Be as specific as you can. :)
Did you mean which framework to use? Probably AFNetworking is the most popular now. I’m interested to see some network tests using `NSURLProtocol`. In this case it doesn’t actually matter what network framework is used underhood ;)
No, I mean what service. For example, a weather API? Or perhaps Twitter?
My vote would be for google data/youtube api.
Use of XCTestExpectation for async calls would seem to make sense if that is the apparent Apple prescribed way of async testing.
I think Twitter API would be a good example as it has an easily consumable API. Also allows you to TDD custom objects and a table view.
Weather could be too simplistic – only a few end points, but for an example like this it may work well. No need to deal with OAuth, just fetch location, lookup daily/weekly forecast.
I think those are the most sensible options.
Maybe we can build a simple GitHub client? GitHub’s public API looks quite pleasant to work with.
I like the idea about using GitHub’s api as well. How about not exactly GitHub client which will be used to navigate thru repositories and notifications, but instead let’s build an app to encourage people to do open source! Using GitHub we can see who user follows and who follows him back. We can know user’s public activity and probably the score calculated by GitHub. We can show the user that his friends are doing open source and somehow to encourage him too. Maybe some kind of badges or bets on a particular opened issue like “I bet you won’t fix this issue in a week!”. Maybe GameCenter can be added too)
Flickr has a pretty easy API to use and would be easy to relate the data into a conventional UI experience of a river of images. iTunes also has a pretty simple API for accessing lists of most popular apps/music/etc.
My vote is for something like Flickr since it also would require async loading of the images in addition to the API call.
How about an app for people search? You enter a nickname, email, and/or real name and the app tries to find a GitHub account for the person (if found – it shows activity, number of contributions and so on), twitter account (if found it shows a few latex twits and maybe some favourites and etc), Facebook account (if found – it shows something available from there too), LinkedIn and etc. Finally it allows to create a contact in users Address book with all information entered. And as these services are social networks means user will have some friends (or people he follow), it may also be interesting to be able to open list of friends and then open a friend and to perform similar search across all the services available.
This seems to be interesting to me because it will use APIs from different services. Probably it will have some some non-obvious data model in CoreData (I would prefer that the case study app uses CoreData).
How about writing an app which can parse your Podfile.lock (can be added using different methods) and then it will check what pods has been updated, it will generate nice links to see the diff from the version you are using to the most recent version. It can be OS X + iOS applications with some shared code and it might also adopt new Handoﬀ feature from Yosemite and iOS8.
AFNetworking seems to be very popular.
If not going for the pictures / imaging API, showing how to test using one of the Picker API would be really interesting. Core Data is also an Apple technology that can be difficult to master (but I’m not sure that it is interesting on the testing point of view given the references available online).
All in all, I’m eagerly interested in seeing the evolution of the app and design, which is where one can hardly find examples and references.
I’d love to see:
* Native networking (NSURLSession) or CloudKit
* A smattering of the new iOS 8 things (Today extension, etc)
I know I’ll like whatever you end up doing, though :-)
i am a big fan of app code in objective-c and test code in swift.
What you all think about using this – Marvel API ? Comics are good choice )
+1 for having an app communicating with an API like Twitter.
Also interesting in seeing how to deal with:
– local/remote notifications
Thank you everybody for the great suggestions! I think making a request to some API, then scrolling through paged results, would be most helpful. Flickr is a great example. But I’m intrigued that a Marvel API even exists! It looks really clean, too. What do you think? I need to move past “which API” to “what use cases”.
I think the Marvel API is cool! Let’s do this!
Some things I would like to see:
* Reactive Cocoa
* Integration with a login service (facebook/twitter), preferable by using the provided SDK.
Also yes please on the Marvel API. Something interesting would be allow user to rate, bookmark and browse the comics. Probably integration with Parse or a similar backend would be required (which would be very interesting to see as well).
I’m really looking forward seeing what you do!
Hi Jon – looking forward to following this case study (I develop for OS X and all the examples I see everywhere are for iOS but it translates OK).
I think one of the biggest things for beginning iOS / OS X developers as far as TDD goes is that the art of creating an interface is so visual with Interface Builder i.e. drag ‘n drop etc, that one of the biggest draws for easy development is how quickly we can design a UI – before you know it, with the odd view controller and a storyboard thrown in and a segue or two a lot of app design can be done fairly quickly. Its not then always clear how TDD fits into this pattern. In particular doing things the Apple way and overriding ‘preparesForSegue’ comes to mind here.
I tend to knock up a UI quickly at the beginning stage of an app to try and understand what my new app is supposed to do since this is so easy – and from here I can then see where TDD comes in so its a bit of a chicken & egg sort of situation – but I then sort of feel guilty that I have something working without having done much TDD!
I don’t think Apple encourages TDD too much given how much dependance we are taught to embrace with object controllers & bindings etc – a lot of app design then becomes virtually invisible and picking apart someone else’s code sometimes only shows half the story until you look at IB and the bindings side of things.
On the other hand, not using bindings does lead to a lot of glue code. Coming from OS X where we have been binding UI’s for a long time now and then comparing with iOS code, iOS does seem a bit long winded for some types of interaction. Then of course there’s animation – TDD with animation! Not even begun to think of the implications here, thoughts for another day perhaps.
It will be interesting to follow your example building this app to see what your approach is and how we can better understand TDD within an overall app design context. Can’t wait!
Thanks, Bob. As for the tension between rapid prototyping and TDD, check out my posts on spike solutions. Spikes are important with frameworks, because the flow of control isn’t contained in the code we write.
Where are you posting the case study? I’d like to work through it to make some concepts more concrete to myself.
You can find the code at https://github.com/jonreid/MarvelBrowser, but the case study is currently generating more posts than code. For example, the next thing I want to do is add an acceptance test that does actual networking — which makes it unsuitable as a unit test. This led to me writing https://qualitycoding.org/slow-tests/ before continuing with the code.