0

テーブル行セルのタップを自動化したときに、表示されたビュー コントローラーが存在するかどうかをテストしようとしています。コントローラーのpresentedViewControllerが特定のタイプのクラスであるかどうかをテストしようとすると、常にnilになります。新しく提示されたView Controllerが提示されたView Controllerに移行していると仮定しているため、[controller presentedViewController]はnilです。

Cedar BDD テスト フレームワークを使用しています。自動化された「タップ」機能を提供するために、Pivo​​talCore ライブラリをインストールしました。

仕様コードは次のとおりです。

#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 でないかどうかをテストする前に、1 秒か 2 秒待つ必要がありますか? もしそうなら、どうすればいいですか?

セルがタップされた後に実行されるコードは次のとおりです。

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];

セルがタップされた後にこのコードが実際に実行されることを再確認しました。します。

ありがとうございました!

4

1 に答える 1

0

Google cedar-discuss グループ ( https://groups.google.com/forum/#!forum/cedar-discuss )の助けを借りて、私はそれを理解することができました。

必要だったのは次のとおりです。

  1. presentViewController をインスタンス化し、それぞれの View Controller に関連付けるために、メインの実行ループを進める必要がありました。
  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

すべてのテストに合格するようになりました。

メンテナの 1 人は、この問題は iOS 8 で行われた内部変更に関連している可能性が最も高いと述べました。presentViewController:animated:completion: が呼び出されるとすぐに、presentedViewController 値を関連付けません。将来的に対処する必要があります。

これが誰かに役立つことを願っています!

アップデート

実行ループを進めることはベスト プラクティスではないことを付け加えるのを忘れていました。これは、問題が修正されるまでの応急処置と見なす必要があります。

于 2014-10-15T22:16:58.667 に答える