Asynchronous Unit Testing

This came up for me in a project last year and came up yesterday on the xcode-users list. How do you unit test something that will run asynchronously, like something that is downloading internet resources who might get here, eventually? I had one such object; it was a web spider that would crawl a website. When I needed to unit test it I used the following code to let it do its thing and then asserted the result afterwards:

[websiteScanner startScan];
while ([websiteScanner isDoneProcessing] == NO) {
    [[NSRunLoop currentRunLoop] runUntilDate:
        [NSDate dateWithTimeIntervalSinceNow:1.0]];
    NSLog(@"Polling...");
}

Hope that helps somebody down the road.

Posted on: February 8, 2006 – 1:48 pm

One Comment

  1. Bryant Luk wrote:

    Polling is somewhat CPU intensive, so I just had another class (my test logger in this case) listen for when a particular notification is posted and stop the run loop when the notification is posted (using CFRunLoopRun() instead of NSRunLoop and CFRunLoopStop(CFRunLoopGetCurrent()).

    Something like this would work if you wanted to stop the main thread’s run loop:

    
    - (void)receivedNotification:(NSNotification*)notification {
      if([notification name] == _nameToStopOn)
        [self performSelectorOnMainThread:@selector(stopRunLoop:)
             withObject:nil waitUntilDone:NO];
    }
    
    - (void)stopRunLoop:(id)object
    {
      CFRunLoopStop(CFRunLoopGetCurrent());
    }
    

    I don’t think there’s anything wrong with this implementation but YMMV. You can even add NSTimers that call methods on particular objects (such as your OCUnit test class if you’re using that) every second to do NSLog(@”Polling…”);.

    I haven’t done it, but I’m sure you could just do something like key value observing as well and stop the run loop in the observing method if the property is KVO and KVC compliant.

    BTW, the only reason I mention the above is that because for some reason some of my sources on the run loop would never become active when using polling, even when left for a significant amount of time. When I switched to using the above instead of using polling, the tests were able to complete and also were much faster.

Post a Comment | Comment RSS feed