Sharing Cocoa

Learn from my mistakes.

Test Your Code

Last july, I was the instructor of the Ironhack for the Core Data and Unit Testing week. One of my goals was teaching the students how to do testing and write proper tests. Most of these students were experienced developers, but even in that case it isn't for clear everybody what to test.

Let me give you an example. You are awesome now, so you are using Core Data for your model. You are so awesome that you have moved all the business logic to your model, even the fetch requests (NSFetchRequest). Those fetch requests that, when executed, return the subset of data that you want. You set the entity name in the fetch request, the sort descriptor(s) and a predicate and it does the magic for you.

An extremely simple instance of this code is:

+ (NSFetchRequest *) fetchForAllChecklists {
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:checklistEntityName];

    return fetchRequest;

It is very easy to be tempted to test that the fetch returns the right objects. But that is wrong. If you test that this fetch returns the right objects, you would be testing whether Apple's code works when provided with that fetch request. Instead, you should test that with this method you are able to generate the expected fetch.

You should (almost) never test Apple's code or anybody else's for that sake, but rather assume that it works. And only in the case that you have strong reasons to believe that their code fails, you may write a test and, if your case is proved, submit a bug report with it.

The proper test for that piece of code would then be:

- (void) testFetchForAllChecklistsIsNotNil {
    NSFetchRequest *fetchRequest = [CheckList fetchForAllChecklists];

    XCTAssertNotNil(fetchRequest, @"Fetch request for all checklists must not be nil.");

- (void) testFetchForAllChecklistsEntityIsChecklist {
    NSFetchRequest *fetchRequest = [CheckList fetchForAllChecklists];

    XCTAssertEqual(fetchRequest.entityName, checklistEntityName,
                   @"Fetch request for all checklists must use CheckList as entity name.");