views:

540

answers:

4

I'm trying out test driven development in a toy project. I can get the tests working for the public interface to my classes (although I'm still on the fence because I'm writing more testing code than there is in the methods being tested).

I tend to use a lot of private methods becuase I like to keep the public interfaces clean; however, I'd still like to use tests on these methods.

Since Cocoa is a dynamic language, I can still call these private methods, but i get warnings in my tests that my class may not respond to these methods (although it clearly does). Since I like to compile with no warnings here are my questions:

  1. How do i turn off these warnings in Xcode?
  2. Is there something else I could do to turn off these warnings?
  3. Am I doing something wrong in trying 'white box' testing?
+2  A: 

Looks like another question has the answer: http://stackoverflow.com/questions/194666/is-there-a-way-to-suppress-warnings-in-xcode

Andrew Burns
That has part of the answer, but the best (or at least a more complete) solution for a particular case is probably related to either Peter's answer or my answer.
Quinn Taylor
+10  A: 

How do i turn off these warnings in Xcode?

Don't.

Is there something else I could do to turn off these warnings?

Don't.

Am I doing something wrong in trying 'white box' testing?

No.

The solution is to move your private methods to a category in its own header. Import this header into both the real class and test-case class implementation files.

Peter Hosey
+1 — Great suggestion! For a little further detail, check out this question/answer: http://stackoverflow.com/questions/1020070/#1020330 The private header containing the category with private methods can be named MyClass_Private.h, for example.
Quinn Taylor
Thanks for this answer. I'm still not sure about it, but I must admit that there is a 'fun' element of writing a test and then making it pass.
Abizern
+4  A: 

Remember that there's actually no such thing as "private methods" in Objective-C, and it's not just because it's a dynamic language. By design, Objective-C has visibility modifiers for ivars, but not for methods — it's not by accident that you can call any method you like.

@Peter's suggestion is a great one. To complement his answer, an alternative I've used (when I don't want/need a header just for private methods) is to declare a category in the unit test file itself. (I use @interface MyClass (Test) as the name.) This is a great way to add methods that would be unnecessary bloat in the release code, such as for accessing ivars that the class under test has access to. (This is obviously less of an issue when properties are used.)

I've found this approach makes it easy to expose and verify internal state, as well as adding test-only methods. For example, in this unit test file, I wrote an -isValid method for verifying correctness of a binary heap. In production, this method would be a waste of space, since I assume a heap is valid — I only care about it when testing for unit test regressions if I modify the code.

Quinn Taylor
A: 

While having a private header or defining your own category are probably more correct solutions there is also another very simple solution: cast the object to (id) before calling the method.

Jon Steinmetz