You can get unit tests to view alerts pretty easily by exchanging the "show" UIAlertView implementation. For example, this interface gives you several testing options:
@interface UIAlertView (Testing) + (void)skipNext; + (BOOL)didSkip; @end
with this implementation
#import <objc/runtime.h> @implementation UIAlertView (Testing) static BOOL skip = NO; + (id)alloc { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ Method showMethod = class_getInstanceMethod(self, @selector(show)); Method show_Method = class_getInstanceMethod(self, @selector(show_)); method_exchangeImplementations(showMethod, show_Method); }); return [super alloc]; } + (void)skipNext { skip = YES; } + (BOOL)didSkip { return !skip; } - (void)show_ { NSLog(@"UIAlertView :: would appear here (%@) [ title = %@; message = %@ ]", skip ? @"predicted" : @"unexpected", [self title], [self message]); if (skip) { skip = NO; return; } } @end
You can write unit tests, for example. eg:
[UIAlertView skipNext];
If you want to automate pressing a certain button in alert mode, you will need more magic. The interface receives two new class methods:
@interface UIAlertView (Testing) + (void)skipNext; + (BOOL)didSkip; + (void)tapNext:(NSString *)buttonTitle; + (BOOL)didTap; @end
which go as follows
static NSString *next = nil; + (void)tapNext:(NSString *)buttonTitle { [next release]; next = [buttonTitle retain]; } + (BOOL)didTap { BOOL result = !next; [next release]; next = nil; return result; }
and the show method becomes
- (void)show_ { if (next) { NSLog(@"UIAlertView :: simulating alert for tapping %@", next); for (NSInteger i = 0; i < [self numberOfButtons]; i++) if ([next isEqualToString:[self buttonTitleAtIndex:i]]) { [next release]; next = nil; [self alertView:self clickedButtonAtIndex:i]; return; } return; } NSLog(@"UIAlertView :: would appear here (%@) [ title = %@; message = %@ ]", skip ? @"predicted" : @"unexpected", [self title], [self message]); if (skip) { skip = NO; return; } }
You can test it the same way, but instead of skipNext you would say which button to click. For instance.
[UIAlertView tapNext:@"Download"]; // do stuff that triggers an alert view with a "Download" button among others STAssertTrue([UIAlertView didTap], @"Download was never tappable or never tapped");