2015-12-05 2 views
1

У меня есть IBAction на мой взгляд, контроллер, который выглядит как этотIOS TestCase для метода, который включает в себя NS Таймер

-(IBAction)signUpAction:(id)sender 
{ 
    AppDelegate *appDel = [[UIApplication sharedApplication]delegate]; 

    //check for internet Connection 
    if(appDel.isReachable) 
    { 
     //Internet Connection available 
     //perform animation od buttons and imagie view 
     [self fallDownAnimation]; 

     //after animation perform model segue to corresponding view controller 

     NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:0.8f target:self selector:@selector(performRegistrationPageSegue) userInfo:nil repeats:NO]; 
     [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 
    } 
    else 
    { 
     //No internet Connection 
     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ALERT_VIEW_TITLE message:@"No Internet Connection" delegate:self cancelButtonTitle:nil otherButtonTitles:@"Okay", nil]; 
     [alert show]; 
    } 
} 



-(void)performRegistrationPageSegue{ 
    [self performSegueWithIdentifier:@"registerVCSegue" sender:self]; 
} 

Я хочу, чтобы написать тест по методу signUpAction и проверить, если выполняется Segue. Так как у него есть таймер, тестовый сценарий, который я написал, терпит неудачу. мне нужен способ, чтобы проверить следующее условие

Мой текущий метод TestCase является

-(void)testRegisterViewControllerSegueOnAvailableInternetConnection{ 
    AppDelegate *appDel = [[UIApplication sharedApplication]delegate]; 
    appDel.isReachable = YES; 
    id loginMock = [OCMockObject partialMockForObject:_initialViewControllerToTest]; 

    [[loginMock expect] performSegueWithIdentifier:@"registerVCSegue" sender:[OCMArg any]]; 

    [loginMock performSelectorOnMainThread:@selector(signUpAction:) withObject:_initialViewControllerToTest.signUpButton waitUntilDone:YES]; 

    XCTAssert([loginMock verify],@"Segue to Register Page not Performed on Sign Up Click"); 
} 

ответ

1

Вам необходимо войти в цикл обработки событий в течение периода времени, так что событие таймера может быть обработан. В основном это невозможно для полного кода теста регрессии, не делая этого. Вот упрощенный метод:

// Wait inside the event loop for a period of time indicated in seconds 

+ (void) waitFor:(NSTimeInterval)maxWaitTime 
{ 
    int numSeconds = (int) round(maxWaitTime); 
    if (numSeconds < 1) { 
    numSeconds = 1; 
    } 

    for (; numSeconds > 0 ; numSeconds--) @autoreleasepool { 
    const int maxMS = 1000; 
    const int incrMS = 1; 
    const double seconds = 1.0/(maxMS/incrMS); 

    for (int ms = 0 ; ms < maxMS; ms += incrMS) @autoreleasepool { 
     // One pass through the run loop for each time interval 
     NSDate *maxDate = [NSDate dateWithTimeIntervalSinceNow:seconds]; 
     [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:maxDate]; 
    } 
    } 

    return; 
} 

Более сложный осущ с селектором, который можно назвать, чтобы вернуться, когда проверяемое условие истинно:

+ (BOOL) waitUntilTrue:(id)object 
       selector:(SEL)selector 
      maxWaitTime:(NSTimeInterval)maxWaitTime 
{ 
    NSAssert(object, @"object is nil"); 
    NSAssert(selector, @"selector is nil"); 
    NSMethodSignature *aSignature = [[object class] instanceMethodSignatureForSelector:selector]; 
    NSInvocation *anInvocation = [NSInvocation invocationWithMethodSignature:aSignature]; 
    [anInvocation setSelector:selector]; 
    [anInvocation setTarget:object]; 

    // Invoke test condition method once before the timing loop is entered, so that the 
    // event loop will not be entered if the condition is initially TRUE. 

    BOOL state; 

    [anInvocation invoke]; 
    [anInvocation getReturnValue:&state]; 

    if (state) { 
    return TRUE; 
    } 

    // The condition is FALSE, so enter the event loop and wait for 1 second 
    // each iteration through the loop. The logic below makes sure that the 
    // 1 second wait will be done at least once, even if wait time is less 
    // than a full second. 

    int numSeconds = (int) round(maxWaitTime); 
    if (numSeconds < 1) { 
    numSeconds = 1; 
    } 

    for (; numSeconds > 0 ; numSeconds--) @autoreleasepool { 
    NSDate *maxDate = [NSDate dateWithTimeIntervalSinceNow:1.0]; 
    [[NSRunLoop currentRunLoop] runUntilDate:maxDate]; 

    [anInvocation invoke]; 
    [anInvocation getReturnValue:&state]; 

    if (state) { 
     return TRUE; 
    }  
    } 

    return FALSE; 
} 
+0

Как я могу использовать эту логику относительно моего кода ? :( –

+0

Вы просто вставляете метод в тестовый файл и вызываете его после добавления NSTimer в цикл событий. Просто начните с вызова waitFor, пока не поймете, как все работает. Метод waitUntilTrue позволяет быстрее вернуться в случае где известный селектор вернет true в результате некоторого асинхронного состояния. – MoDJ

+0

Kool. Понял, как он работает. Спасибо тонну :) –