OCUnit 使用 UINavigationController 和 UITableView 测试我的应用程序
我想编写集成应用程序测试来测试完整的 CRUD 操作。我有一个表视图来列出所有对象。用户可以单击“添加”按钮推送新的详细视图控制器来添加新对象;他们可以单击现有对象来推送详细视图控制器来重命名该对象;他们还可以从列表中删除该对象。
我很高兴尝试使用 OCUnit 来测试我的应用程序。然而,我遇到了一些奇怪的错误。我正在使用 UITabBarController + UINavigationController。我的 UINavigationController 中有超过 3 层的 PushViewController。如果我使用 [self.navigationController PushViewController:viewControllerAnimated:YES] 测试代码,它主要适用于两个警告:
nested push animation can result in corrupted navigation bar
nested pop animation can result in corrupted navigation bar
我注意到 viewDidAppear 没有被调用,因此出现警告。
然后我尝试通过将animated:YES 更改为animated:NO 来解决此问题。警告消失了。但是,我遇到了另一个错误,根本没有调用 viewDidLoad 。因此视图不会从 NIB 文件加载,并且所有 IB 控件均为 nil。如果我将动画设置为“是”,则情况并非如此。
这是我用来获取 UINavigationController 中根视图控制器句柄的代码。
app = (MyAppDelegate*) [[UIApplication sharedApplication] delegate];
rootVC = ((MyViewController*)[[((UINavigationController*)[app.tabBarController.viewControllers objectAtIndex:0]) viewControllers] objectAtIndex:0]);
我在测试中手动调用此代码来模拟 UITableView 上的单击:
[rootVC tableView:rootVC.tableView didSelectRowAtIndexPath:ip]; // push is called inside this
所以我陷入困境,要么设置动画:是,要么设置动画:否。有人成功使用 OCUnit 通过 UINavigationController + UITableView 测试应用程序吗?如果是这样,您能否分享一些示例代码或您的经验?
I want to write integration application test to test the full CRUD operations. I have a table view to list all objects. User can click "Add" button to push a new detail view controller to add a new object; They can click on an existing object to push a detail view controller to rename the object; They can also delete the object from the list.
I got excited to try out OCUnit to test my app. However, I have ran into some weird bugs. I am using UITabBarController + UINavigationController. I have more than 3 levels of pushViewController in my UINavigationController. If I test the code as it is with [self.navigationController pushViewController:viewController animated:YES] , it mostly works with two warnings:
nested push animation can result in corrupted navigation bar
nested pop animation can result in corrupted navigation bar
I noticed viewDidAppear isn't called hence the warnings.
Then I try to workaround by changing animated:YES to animated:NO. The warnings go away. However, I ran into another bug where viewDidLoad isn't called at all. So the view doesn't load from the NIB file and all the IB controls are nil. This wasn't the case if I set animated to YES.
This is the code I use to get a handle of the root view controller in the UINavigationController.
app = (MyAppDelegate*) [[UIApplication sharedApplication] delegate];
rootVC = ((MyViewController*)[[((UINavigationController*)[app.tabBarController.viewControllers objectAtIndex:0]) viewControllers] objectAtIndex:0]);
I manually called this code in my test to simulate a click on the UITableView:
[rootVC tableView:rootVC.tableView didSelectRowAtIndexPath:ip]; // push is called inside this
So I am stuck either I set animated:YES or animated:NO. Does anyone successfully use OCUnit to test apps with UINavigationController + UITableView? If so, could you please share some sample code or your experience?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,对于单元测试,不要从应用程序委托获取根视图控制器。实际的根视图控制器是一个单例,单元测试中的单例会创建测试间依赖关系。相反,让测试设置(并拆除)自己的视图控制器实例。
某些类型的测试需要视图控制器加载其笔尖 - 例如,创建表视图。对于这些测试,请调用
要测试视图控制器是否被推送,请使用实际视图控制器的测试子类并覆盖
navigationController
以返回可以验证的模拟对象。例如,然后让您的测试创建一个
TestingMyViewController
和一个模拟。设置模拟,并将其分配给测试子类。调用您要测试的方法,然后验证模拟导航控制器是否收到了您期望的调用以及您期望的参数。First off, for unit tests, don't get your root view controller from your app delegate. The actual root view controller is a singleton, and singletons in unit tests create inter-test dependencies. Instead, have the test set up (and tear down) its own view controller instance.
Certain kinds of tests require the view controller to load its nib — for example, to create the table view. For these tests, call
To test that a view controller is pushed, use a testing subclass of your actual view controller and override
navigationController
to return a mock object you can verify. For example,Then have your test create a
TestingMyViewController
and a mock. Set up the mock, and assign it to the testing subclass. Invoke the method you want to test, then verify that the mock navigation controller received the call you expected, with the argument you expected.