gpt4 book ai didi

ios - View Controller TDD

转载 作者:IT王子 更新时间:2023-10-29 05:30:36 27 4
gpt4 key购买 nike

我正在尝试在我的项目中添加一些单元测试来测试 View Controller 。但是,我似乎在看似简单的事情上遇到了问题。我创建了一个我将引用的示例项目。 https://github.com/pangers/ViewControllerTesting

该示例包含一个 UINavigationController 作为初始 View Controller 。 UINavigationController 的 Root View Controller 是 FirstViewController。 FirstViewController 上有一个连接到 SecondViewController 的按钮。在 SecondViewController 中有一个空的文本字段。

我要添加的两个测试是:
1) 检查 FirstViewController 中的按钮标题是否为“下一个屏幕”。
2) 检查 SecondViewController 中的文本字段是否为空,""。

我听说将您的 swift 文件添加到主要目标和测试目标的报告不是一个好习惯。但最好将您想要在测试中访问的任何内容公开并将主要目标导入测试。这就是我所做的。 (我还将主要目标的“定义模块”设置为"is",因为这也是我在几篇文章中读到的内容)。

在 FirstViewControllerTests 中,我使用以下内容实例化了第一个 View Controller :

var viewController: FirstViewController!

override func setUp() {
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle(forClass: self.dynamicType))
let navigationController = storyboard.instantiateInitialViewController() as UINavigationController
viewController = navigationController.topViewController as FirstViewController
viewController.viewDidLoad()
}

我已经添加了测试:
func testCheckButtonHasTextNextScreen() {
XCTAssertEqual(viewController.button.currentTitle!, "Next Screen", "Button should say Next Screen")
}

同样,对于 SecondViewControllerTest,我使用以下方法进行了设置:
var secondViewController:SecondViewController!

override func setUp() {
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle(forClass: self.dynamicType))
let navigationController = storyboard.instantiateInitialViewController() as UINavigationController
let firstviewController = navigationController.topViewController as FirstViewController
firstviewController.performSegueWithIdentifier("FirstToSecond", sender: nil)
secondViewController = navigationController.topViewController as SecondViewController
secondViewController.viewDidLoad()
}

和测试:
func testTextFieldIsBlank() {
XCTAssertEqual(secondViewController.textField.text, "", "Nothing in textfield")
}

他们都失败了,我不太确定为什么。我怀疑我实例化 View Controller 的方式不正确。实例化 View Controller 的最佳方法是使用 Storyboard(就像它在现实生活中运行一样)?或者可以通过以下方式实例化:
var viewController = FirstViewController()

你们在 swift 中使用 TDD 和 View Controller 有什么经验?

我将 Swift 与 XCode 6.1.1 一起使用。

提前致谢。

已解决

好的,在考虑了 modocache 和 Mike Taverne 的答案之后,我找到了我的解决方案,并且我学到了一些东西,我将在下面写下来。

1)我公开了我想测试的任何类/方法/变量。我不需要将 swift 文件添加到测试目标。

2)我只需要为“主要”目标设置“定义模块”(而不是“测试”目标或整个项目)

3) 实例化storyboard时,bundle应该设置为nil而不是NSBundle(forClass: self.dynamicType),否则测试会失败。

4)正如 modocache 所说,最好给你的 View Controller 一个 StoryboardID 并像这样实例化它们:
viewController = storyboard.instantiateViewControllerWithIdentifier("FirstViewController") as FirstViewController

但是,像这样实例化 View Controller 只能单独实例化 View Controller ,而不是它可能嵌入的任何导航 Controller 。这意味着,试图做
XCTAssertFalse(viewController.navigationController!.navigationBarHidden, "Bar should show by default")

将导致 nil 异常。我确认了这一点
XCTAssertNil(viewController.navigationController?, "navigation controller doesn't exist")

这导致了成功的测试。

因为我想检查 FirstViewController 中导航栏的状态,所以必须像这样实例化 View Controller :
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = storyboard.instantiateInitialViewController() as UINavigationController
viewController = navigationController.topViewController as FirstViewController

现在进行测试
XCTAssertFalse(viewController.navigationController!.navigationBarHidden, "nav bar should be showing by default")

结果测试成功。

5) let _ = viewController.view 确实触发了 viewDidLoad() 测试确认

6) let _ = viewController.view 不会触发 viewWillAppear(),然后我也假设任何事情。 viewController.viewWillAppear(false/true) 需要手动调用才能触发(通过测试确认)。

希望这对人们有所帮助。如果有人想玩它,我会将更新的项目推送到 GitHub(上面的链接)。

更新 #2

综上所述,我仍然不知道如何从第一个 View Controller 转换到第二个 View Controller (以便我可以在 SecondViewControllerTests.swift 中测试导航栏属性)。我试过了
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let nc = storyboard.instantiateInitialViewController() as UINavigationController
let firstVC = nc.topViewController as FirstViewController
firstVC.performSegueWithIdentifier("FirstToSecond", sender: nil)
secondVC = nc.topViewController as SecondViewController

这导致了错误。

我也试过
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let nc = storyboard.instantiateInitialViewController() as UINavigationController
let firstVC = nc.topViewController as FirstViewController
firstVC.toSecondVCButton.sendActionsForControlEvents(UIControlEvents.TouchUpInside)
secondVC = nc.topViewController as SecondViewController

这没有用。

我最终尝试了
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let nc = storyboard.instantiateInitialViewController() as UINavigationController
vc = storyboard.instantiateViewControllerWithIdentifier("Second") as SecondViewController
nc.pushViewController(vc, animated: false)
let _ = vc.view
vc.viewWillAppear(false)

这与我的测试完美配合(允许我访问导航栏属性)!

最佳答案

我同意@MikeTaverne 的回答:我更喜欢访问-[UIViewController view]为了触发-[UIViewController viewDidLoad] ,而不是直接调用它。查看 FirstViewController 的测试是否失败一旦你使用它就离开:

viewController = navigationController.topViewController as FirstViewController
let _ = viewController.view

我还建议在 Storyboard 中同时提供两个 View Controller 标识符。这将允许您直接实例化它们,而无需通过 UINavigationController 访问它们。 :
var secondViewController: SecondViewController!

override func setUp() {
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle(forClass: self.dynamicType))
secondViewController = storyboard.instantiateViewControllerWithIdentifier("SecondViewController")
as SecondViewController
let _ = secondViewController.view
}

查看我关于测试的演讲 UIViewController在布鲁克林 swift 了解详情: https://vimeo.com/115671189#t=37m50s (我的演讲开始于 37'50"标记)。

关于ios - View Controller TDD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28733016/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com