iPhreaks is a podcast done as a panel discussion. The panel often brings strong experience from other platforms. (In fact, iPhreaks is the iOS cousin to the Ruby Rogues panel.) They already discussed TDD in episode 95. Following up on that, I'm honored that they invited me as their guest to talk more about TDD and Testing in episode 116.
iPhreaks Podcast Outline
Here's the outline of our discussion:
- Tools For Testing and Test-Driven Development (TDD)
- Matching/Matchers
- Getting Started with OCHamcrest
- Partial Matching
- Mocking and Stubbing
- TDD Process and Workflow
- TDD vs Unit Testing
- iOS Code That Doesn’t/Does Adapt Well to TDD
- User Interface Testing
- End-to-End Testing
- Communication and Collaboration
- OCMock, OCMockito
- OCMockito with Swift?
- Inside-Out vs. Outside-In
Things I Wish I'd Said
Of course, listening to the podcast, I realize there are things I wish I'd said, such as:
- The difference between mocks and stubs.
- That the purpose of mocks is to verify interactions.
- That you don't need a mocking framework to make mocks and stubs. In fact, I recommend against it at first.
Chuck asked,
So let’s say that you wanted to add a feature to Skype where, every time somebody typed the word “whistle” their phone would whistle at them. How would you TDD something like that?
Here's how I'd begin to break it down:
- Text detection to create a Whistle command.
- Executing the Whistle command, which plays a sound.
- What if the user pastes text instead of typing it, and it contains multiple commands?
It's challenging to take a workflow and break it down into smaller tests. Software design principles help a lot. In particular, don't embed control into your UI. Instead, design a UI-ignorant command architecture.
Don't embed control into your UI. Instead, design a UI-ignorant command architecture.
What Would You Say, or Ask?
I hope you'll check out the podcast. I find the panel discussion format really engaging, and had a lot of fun.
If you'd been on the panel, what would you have said or asked about iOS TDD and Testing? Leave a comment below to have your say, or ask your question.
Hi Jon
Many thanks for your screencasts and insights of doing testing on iOS. This really got me started to do some serious testing on iOS. lately i read some articles about TDD. The one thing that bugs me, is that i need to run all of my tests on the simulator, and this is time consuming on larger project. So my question is, would it make sense to create a Test Bundle for unit test which doesn’t need to run the simulator, or is this not a good idea?
Besides feedback speed, it also seems that when i mock out my dependencies (with stubbing or mocking) it almost feels like i am testing the implementation instead the behavior. This makes my tests brittle and often if i refactor production code the test code is broken too. Otherwise, when i tried to only fake the boundaries and use real object for testing the dependencies, is makes my test fail, if i introduced a bug in the dependencies. Do you have similar issues with that, or how are you doing tests which involves classes which are under your control? Do they even need tests?
Tanks alot
Chris,
The first thing to try with tests that take too long is to use a different App Delegate during testing. See https://qualitycoding.org/app-delegate-for-tests/
You’re right, tests that involve stubbing and mocking are more brittle. With any testing technique, it’s easy to say, “Oh my gosh! Now I can write All These Tests,” and over-apply the technique. Then it bites you, and you learn to ask, “Is there a way I can test this with fewer dependencies, or without knowing about them at all?”
But quite often, stubs and mocks are still a good way forward. When you use them, you are verifying interactions between classes. It’s like guaranteeing a contract.
So what I’ve learned to do is centralize the places in my my tests that set up these dependencies. Sometimes this can be done in -setUp. But quite often, I create new test helper methods. Then when the production code changes (and I’ve done everything right), there’s only place in the test code that needs to be updated to reflect this change, and all the tests stay happy.