2013-06-23 41 views
5

Tôi muốn tạo một thử nghiệm tích hợp cho thấy rằng một hành động nhất định dẫn đến hiển thị một bộ điều khiển xem phương thức. Các storyboard được thiết lập với 2 viewcontrollers, một với một lớp ViewController tùy chỉnh thứ hai với một lớp UIViewController mặc định và tiêu đề "thứ hai". Segue được thiết lập để được phương thức với định danh "modalsegue". Chạy ứng dụng trong trình mô phỏng hoạt động rực rỡ, nhưng tôi gặp rất nhiều rắc rối khi xác định một thử nghiệm chính xác.Thử nghiệm tự động các phân đoạn

ViewController.m:

@implementation ViewController 

- (IBAction)handleActionByPerformingModalSegue { 
    [self performSegueWithIdentifier:@"modalsegue" sender:self]; 
} 
@end 

Test:

- (void)testActionCausesDisplayOfSecondViewController { 
    ViewController * vc = 
     [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil] 
      instantiateViewControllerWithIdentifier:@"ViewController"]; 

    [vc handleActionByPerformingModalSegue]; 
    STAssertEquals(vc.presentedViewController.title, @"second", 
     @"Title of presented view controller should be second but is %@", 
     vc.presentedViewController.title, nil); 
} 

Chạy kết quả kiểm tra tại đầu ra sau đây:

2013-06-23 17:38:44.164 SeguesRUs[15291:c07] Warning: Attempt to present <UIViewController: 0x7561370> on <ViewController: 0x7566590> whose view is not in the window hierarchy! 
SeguesRUsTests.m:33: error: -[SeguesRUsTests testActionCausesDisplayOfSecondViewController] : '<00000000>' should be equal to '<9c210d07>': Title of presented view controller should be second but is (null) 

Tôi đang làm gì sai? Có cách nào dễ dàng để tránh tin nhắn đầu tiên không?

+0

tốt, có lẽ bạn nên chuyển sang một khung trình độ cao hơn mà sẽ thực sự thử nghiệm giao diện người dùng và không một số phương pháp nội - đối với giao diện người dùng tự động hóa của thẳng thắn-dưa leo dụ của Apple. – Sulthan

Trả lời

0

Đây là những gì tôi làm. Giả sử tôi có DocumentsVC với segue được kích hoạt thủ công (DocumentsDetailVC) được kết nối. Dưới đây là thiết lập của tôi và sau đó tôi kiểm tra 1. sự tồn tại của segue và sau đó 2. Tôi buộc bộ điều khiển xem (trong trường hợp của tôi, tôi đăng thông báo) để kích hoạt performSegueWithIdentifier của nó và chặn phương thức PrepareForSegue để xem mọi thứ cho bộ điều khiển xem mới (DocumentsDetailVC) được thiết lập. Điều này bao gồm các phương pháp swizzling.

Tôi không phải là tôi sử dụng OCHamcrest/OCMockito để kiểm tra đơn vị và tất cả các phân đoạn của tôi được đặt tên sau bộ điều khiển xem mục tiêu được thêm bởi "Segue" ([self appDelegate] segueIdentifierForClass: [SomeClass class]]).

- (void)setUp 
{ 
    [super setUp]; 

    _isPad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad; 

    realPrepareForSegue = @selector(prepareForSegue:sender:); 
    testPrepareForSegue = @selector(documentsBrowserTest_prepareForSegue:sender:); 

    UIStoryboard *storyboard = nil; 
    if (_isPad) { 
    storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil]; 
    } 
    else { 
    storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPad" bundle:nil]; 
    } 
    UINavigationController *navController = [storyboard instantiateInitialViewController]; 
    self.sut = (DocumentsBrowserVC *)navController.topViewController; 
    [self.sut view]; 
} 


- (void)test_DocumentsDetailsVCSegueConnected 
{ 
    if (_isPad == FALSE) { 
    STAssertNoThrow([self.sut performSegueWithIdentifier:[[self appDelegate] segueIdentifierForClass:[DocumentsDetailVC class]] sender:self], @"DocumentsDetailVC should be connected"); 
    } 
} 


- (void)test_providerDidSelectPathLevelObject_triggersDocumentsDetailsVCSegueSectionIdFile 
{ 
    [DocumentsBrowserTest swapInstanceMethodsForClass:[DocumentsBrowserVC class] 
               selector:realPrepareForSegue 
              andSelector:testPrepareForSegue]; 

    [[NSNotificationCenter defaultCenter] addObserver:self.sut selector:@selector(providerDidSelectPathLevelObject:) name:ProviderDidSelectPathLevelObjectNotification object:nil]; 

    // when  
PathLevelObject *plo = self.pathLevelObjects[SectionIdFile][4]; 
NSDictionary *userInfo = @{OBJECT_KEY : plo , BROWSER_AREA_KEY : @(DocumentsFolder)}; 
[[NSNotificationCenter defaultCenter] postNotificationName:ProviderDidSelectPathLevelObjectNotification object:nil userInfo:userInfo]; 

    // then 
    if (_isPad == FALSE) { 
    assertThat(NSStringFromClass([objc_getAssociatedObject(self.sut, storyboardSegueKey) class]), is(equalTo(@"UIStoryboardPushSegue"))); 
    assertThatBool([[objc_getAssociatedObject(self.sut, storyboardSegueKey) destinationViewController] isKindOfClass:[DocumentsDetailVC class]], is(equalToBool(TRUE))); 
    assertThat(objc_getAssociatedObject(self.sut, senderKey), is(equalTo(self.sut))); 
    } 
    else { 
    assertThatInteger(self.sut.detailViewController.browsingArea, is(equalToInteger(DocumentsFolder))); 
    assertThat(self.sut.detailViewController.pathLevelObject, is(equalTo(plo))); 
    } 


    [[NSNotificationCenter defaultCenter] removeObserver:self.sut]; 

    [DocumentsBrowserTest swapInstanceMethodsForClass:[DocumentsBrowserVC class] 
               selector:realPrepareForSegue 
              andSelector:testPrepareForSegue]; 
} 
+0

Đó là rất nhiều mã kiểm tra để xác minh tương đối ít. Bạn có nói rằng bạn đã có rất nhiều giá trị trong một thử nghiệm như thế này? – fatuhoku

1

Như thông báo lỗi chỉ ra, vấn đề là bạn đang cố gắng để trình bày trên một UIViewController mà xem không có trong hệ thống phân cấp UIWindow.

Cách dễ nhất để sửa chữa nó:

- (void)testExample { 

    // 
    // Arrange 
    // Storyboard 
    // 
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; 

    // 
    // Arrange 
    // View Controller 
    // 
    UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"ViewController"]; 
    [UIApplication sharedApplication].keyWindow.rootViewController = viewController; 

    // 
    // Act 
    // 
    [viewController performSegueWithIdentifier:@"ModalSegue" sender:nil]; 

    // 
    // Assert 
    // 
    XCTAssertEqualObjects(viewController.presentedViewController.title, @"Second"); 

} 
+0

Không phải là '[UIApplication sharedApplication]' sẽ khởi tạo một thể hiện của UIApplication bên trong bài kiểm tra đơn vị của bạn? Điều gì xảy ra ở đó? – fatuhoku

+0

Tôi đang sử dụng phiên bản chia sẻ của 'UIApplication' để truy cập' keyWindow' để tôi có thể đặt 'rootViewController' của nó. –

Các vấn đề liên quan