使用Cedar测试presentedViewController的存在 [英] Testing the existence of a presentedViewController using Cedar

查看:73
本文介绍了使用Cedar测试presentedViewController的存在的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我自动点击表格行单元格时,我正在尝试测试是否存在呈现的视图控制器.当我尝试测试控制器的presentedViewController是否属于给定类型的类时,它总是结果为nil.我假设新的呈现视图控制器正在过渡到成为呈现视图控制器,这就是[controller presentViewController]为零的原因.

I am trying to test if a presented view controller exists when I have automated the tapping of a table row cell. When I attempt to test if the controller's presentedViewController is of a given type of class it always results to nil. I'm assuming the new presented view controller is transitioning to being the presented view controller and that is why the [controller presentedViewController] is nil.

我正在使用Cedar BDD测试框架.我已经安装了PivotalCore库以提供自动的点击"功能.

I am using the Cedar BDD testing framework. I have installed the PivotalCore libs to provide the automated 'tap' functionality.

以下是规范代码:

#import <Cedar-iOS/Cedar-iOS.h>
#import "UITableViewCell+Spec.h"

#import "FMNavigatorViewController.h"

using namespace Cedar::Matchers;
using namespace Cedar::Doubles;

SPEC_BEGIN(FMNavigatorViewControllerSpec)

describe(@"FMNavigatorViewController", ^{
    __block UINavigationController *nav;
    __block FMNavigatorViewController *controller;

    beforeEach(^{
        FSHandle *documents = [FSHandle handleAtUrl:[[BasicFileManager sharedManager] documentsUrl] isDirectory:YES];
        // @todo Remove all files from Recent Files and Local Files.
        // Remove all configured remote connections.
        NSArray *contents = [[BasicFileManager sharedManager] contentsOfDirectoryAtURL:documents.url];
        for (NSURL *url in contents) {
            if (! [url.lastPathComponent isEqualToString:@"Local Files"] && ! [url.lastPathComponent isEqualToString:@"Recent Files"]) {
                NSLog(@"WARNING: Deleting Manager: %@", url.lastPathComponent);
                FileManager *manager = [FileManager fileManagerWithName:url.lastPathComponent];
                [manager deleteFileManager];
            }
        }
        // Create view.
        controller = [[FMNavigatorViewController alloc] initWithDirectory:documents];
        nav = [[UINavigationController alloc] initWithRootViewController:controller];
        // Initiates view lifecycle. Accessing the 'view' will automatically
        // create it.
        nav.view should_not be_nil;
        // Doesn't get called unless properly added to a heirarchy -- which I
        // haven't found the correct process for yet.
        [controller viewWillAppear:NO];
    });

    it(@"should contain Local and Recent Files with no other connections", ^{
        controller should be_instance_of([FMNavigatorViewController class]);
        // Local and Remote Connection Groups
        [controller.tableView.dataSource numberOfSectionsInTableView:controller.tableView] should equal(2);
        // Recent Files and Local Files
        [controller.tableView.dataSource tableView:controller.tableView numberOfRowsInSection:0] should equal(2);
        // Enforce order: Local Files then Recent Files.
        [[[controller.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]] textLabel] text] should equal(@"Local Files");
        [[[controller.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]] textLabel] text] should equal(@"Recent Files");
        // The second group should have one row with description.
        [controller.tableView.dataSource tableView:controller.tableView numberOfRowsInSection:1] should equal(1);
        [[[controller.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]] textLabel] text] should equal(NSLocalizedString(@"CreateRemoteConnection", @""));
    });

    it(@"should display the FM wizard view", ^{
        [[controller.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]] tap];
        controller.presentedViewController should_not be_nil;
        //[nav presentedViewController] should be_instance_of([UINavigationController class]);
        //[controller presentedViewController] should be_instance_of([UINavigationController class]);
    });

});

SPEC_END

最后的测试包含有问题的代码.我的问题是:在测试presentedViewController是否为nil之前,我需要等待一两秒钟吗?如果是这样,我该怎么办?

The very last tests contain the code in question. My question is: do I need to wait a second or two before testing if the presentedViewController is not nil? If so, how do I do this?

这是在点击单元格后应执行的代码:

Here is the code that should execute once the cell has been tapped:

FMWizardViewController *controller = [FMWizardViewController new];
[controller setDelegate:self];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:controller];
nav.navigationBar.tintColor = UIColorFromRGB(BNAV_TINT_COLOR);
[self presentViewController:nav animated:YES completion:nil];

我仔细检查了一下,以确保在敲击单元格后此代码确实被执行了;是的.

I double checked to make sure that this code actually gets ran after the cell is tapped; it does.

谢谢!

推荐答案

借助Google cedar-discuss组(

With the help of the Google cedar-discuss group (https://groups.google.com/forum/#!forum/cedar-discuss) I was able to figure it out.

需要发生的是:

  1. 需要提前主运行循环,以实例化presentedViewController并将其关联到相应的视图控制器
  2. 需要创建整个视图层次结构(窗口,导航控制器,FMNavigationController)

#import <Cedar-iOS/Cedar-iOS.h>

#import "UITableViewCell+Spec.h"

#import "FMNavigatorViewController.h"

// << -- Add this
#define tickRunLoop (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.01, false))

using namespace Cedar::Matchers;
using namespace Cedar::Doubles;

SPEC_BEGIN(FMNavigatorViewControllerSpec)

describe(@"FMNavigatorViewController", ^{
    __block UIWindow *window; // <<-- and this,
    __block UINavigationController *nav;
    __block FMNavigatorViewController *controller;

    beforeEach(^{
        window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        FSHandle *documents = [FSHandle handleAtUrl:[[BasicFileManager sharedManager] documentsUrl] isDirectory:YES];
        // @todo Remove all files from Recent Files and Local Files.
        // Remove all configured remote connections.
        NSArray *contents = [[BasicFileManager sharedManager] contentsOfDirectoryAtURL:documents.url];
        for (NSURL *url in contents) {
            if (! [url.lastPathComponent isEqualToString:@"Local Files"] && ! [url.lastPathComponent isEqualToString:@"Recent Files"]) {
                NSLog(@"WARNING: Deleting Manager: %@", url.lastPathComponent);
                FileManager *manager = [FileManager fileManagerWithName:url.lastPathComponent];
                [manager deleteFileManager];
            }
        }
        // Create view.
        controller = [[FMNavigatorViewController alloc] initWithDirectory:documents];
        nav = [[UINavigationController alloc] initWithRootViewController:controller];
        window.rootViewController = nav;
        [window makeKeyAndVisible];
        // Initiates view lifecycle. Accessing the 'view' will automatically
        // create it.
        nav.view should_not be_nil;
        // Doesn't get called unless properly added to a heirarchy -- which I
        // haven't found the correct process for yet.
        [controller viewWillAppear:NO];
    });

    it(@"should contain Local and Recent Files with no other connections", ^{
        controller should be_instance_of([FMNavigatorViewController class]);
        // Local and Remote Connection Groups
        [controller.tableView.dataSource numberOfSectionsInTableView:controller.tableView] should equal(2);
        // Recent Files and Local Files
        [controller.tableView.dataSource tableView:controller.tableView numberOfRowsInSection:0] should equal(2);
        // Enforce order: Local Files then Recent Files.
        [[[controller.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]] textLabel] text] should equal(@"Local Files");
        [[[controller.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]] textLabel] text] should equal(@"Recent Files");
        // The second group should have one row with description.
        [controller.tableView.dataSource tableView:controller.tableView numberOfRowsInSection:1] should equal(1);
        [[[controller.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]] textLabel] text] should equal(NSLocalizedString(@"CreateRemoteConnection", @""));
    });

    it(@"should display the FM wizard view", ^{
        // Sanity to ensure we are tapping the right cell.
        [[controller.tableView.visibleCells[2] textLabel] text] should equal(NSLocalizedString(@"CreateRemoteConnection", @""));
        [controller.tableView.visibleCells[2] tap];
        tickRunLoop; // <<-- and this.
        controller.presentedViewController should_not be_nil;
        controller.presentedViewController should be_instance_of([UINavigationController class]);
    });

});

SPEC_END

所有测试现在都通过.

一位维护者表示,该问题很可能与iOS 8中的一些内部更改有关;一旦调用presentViewController:animated:completion:,它就不会与presentedViewController值相关联.将来应该解决.

One of the maintainers said that the issue is most likely related to some internal changes made in iOS 8; where it doesn't associate the presentedViewController value as soon as presentViewController:animated:completion: is called. It should be addressed in the future.

我希望这对某人有帮助!

I hope this helps someone!

更新

我忘记补充说,推进运行循环不是最佳实践.在问题解决之前,这应该被视为一个权宜之计.

I forgot to add that advancing the run loop is not best practice. This should be considered a stop-gap until the issue is fixed.

这篇关于使用Cedar测试presentedViewController的存在的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆