Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing of private methods in Xcode

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?
like image 407
Abizern Avatar asked Jul 08 '09 14:07

Abizern


People also ask

How do you unit test private functions in Swift?

Access Control You probably know that you can apply the testable attribute to an import statement in a test target to gain access to entities that are declared as internal. import XCTest @testable import Notes class NotesTests: XCTestCase { ... }

Can we test private methods in unit testing?

Unit Tests Should Only Test Public Methods The short answer is that you shouldn't test private methods directly, but only their effects on the public methods that call them. Unit tests are clients of the object under test, much like the other classes in the code that are dependent on the object.

How do you write test cases for private methods in Swift?

You can't test private methods in Swift using @testable . You can only test methods marked either internal or public . As the docs say: Note: @testable provides access only for “internal” functions; “private” declarations are not visible outside of their file even when using @testable.

Can we write test cases for private methods?

Strictly speaking, you should not be writing unit tests that directly test private methods. What you should be testing is the public contract that the class has with other objects; you should never directly test an object's internals.


1 Answers

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.

like image 187
Quinn Taylor Avatar answered Sep 22 '22 00:09

Quinn Taylor