40

XCTestCase根据关于的默认模板中的评论setUp

Put setup code here; it will be run once, before the first test case.

但是,在 中XCTestCase.h,上面的评论有setUp不同的说法:

Setup method called before the invocation of each test method in the class.

为了确认实际行为,我放了一个NSLoginsidesetUp来计算它被调用的次数:

static int count = 0;

- (void)setUp
{
    [super setUp];
    count++;

    NSLog(@"Call Count = %d", count);
}

这导致该setUp方法在每个测试方法之前被调用(确认注释XCTestCase.h)。

我想使用该setUp方法创建一次测试/模拟对象(例如设置核心数据测试堆栈)。一遍又一遍地创建这些将是处理器密集型的,并且可能非常慢。

所以,

1)setUp实际打算用于什么?开发人员肯定不会一遍又一遍地在其中创建对象吗?

2)我怎样才能在一个中只创建一次XCTestCase这些对象?

4

2 回答 2

91

这里有几点需要讨论:setUp方法的行为和一般的最佳测试实践。

其实有两种 setUp方法:

+ (void)setUp;
- (void)setUp;

类方法 ( + (void)setUp) 在整个测试运行期间只运行一次。

实例方法 ( - (void)setUp) 是默认模板中的方法;它在每次测试之前运行。希望在假设的 Xcode 未来版本中,此注释已更改为// Put setup code here. This method is called before the invocation of each test method in the class.WINK WINK

所以通过这两种方法,你描述的两种行为都是可能的。

关于您的评论:

“开发人员肯定不会一遍又一遍地在其中创建对象吗?”

我的回答是“是的,他们通常是”。“好”单元测试的流行首字母缩写词是 FIRST:

  • 快速地
  • 孤立
  • 可重复
  • 自我验证
  • 及时

隔离是本次讨论的关键:您的测试不应依赖于其他测试留下的任何先前状态。理想情况下,您应该为每个测试拆除并重新创建内存中的核心数据堆栈,这样您就知道您是从零开始的。Graham Lee的这篇文章就是一个很好的例子。您想使用内存中的堆栈,因为a)您可以轻松地将其丢弃,并且b)它应该非常快,因为它只是在内存中并且不会撞击您的磁盘。

如果您发现测试因此运行缓慢(不要过早优化),那么我认为合理的下一步是在您的方法中创建堆栈+ (void)setUp,但每次在您的- (void)setUp方法中创建一个全新的上下文.

于 2014-01-10T09:36:16.123 回答
5

我带着几乎同样的问题来到这里:如何setUp 在 Swift 中执行一次。这是解决方案:

override class func setUp() {
    super.setUp()    
    // ...
}

override class func tearDown() {    
    // ...
    super.tearDown()
}

现在我仍在寻找异步 setUp的解决方案!

于 2016-12-06T11:21:40.210 回答