如何编写单元测试来检查我的属性是否在iOS上的dealloc中发布?

时间:2011-04-28 10:07:23

标签: ios unit-testing tdd dealloc

我对TDD和单元测试都很陌生,我正在尝试一个辅助项目。

我有点坚持单元测试dealloc方法。

我们都知道在dealloc中发布自定义属性并将它们设置为nil是一个好习惯:

-(void) dealloc{
  [myProperty release];
  myProperty = nil;
  [super dealloc];
}

我怎样才能编写一个检查此行为的单元测试?

显然,这不起作用:

[myObject release]
STAssertNil(myObject.myProperty,@"myProperty should be released and set to nil in dealloc")

有什么建议吗? 谢谢!

2 个答案:

答案 0 :(得分:4)

假设您可以执行上述操作,您实际会测试什么?这就是我的想法:

  1. 测试-release会减少retainCount

  2. 测试当retainCount达到零时NSObject的垃圾收集机制调用-dealloc

  3. 测试当调用-dealloc时,myProperty被释放

  4. 这是单元测试的错误粒度,第一点和第二点不是您要测试的业务 - 假设它是由Apple进行的单元测试。所以,上面唯一的一个单元测试是:

      

    测试调用-dealloc时,   myProperty已发布

    现在,这段代码(非常正确)没有任何逻辑,也没有输出。所以,我相信它的单元测试实际上是偏执和无关紧要的(类似于测试编译器实际工作)。

    但如果我确实想测试它,我会这样做:

    OCMockObject *mockProperty = MOCK(NSObject);
    [[mockProperty expect] release];
    myObject.myProperty = mockProperty;
    [myObject dealloc];
    [mockProperty verify];
    

    显然你通常不应该直接调用-dealloc,但如果你想单元测试-dealloc就是你应该做的(或者它不是单元测试)。鉴于这是非常糟糕的做法而且测试收益很少,我认为你不应该打扰。

答案 1 :(得分:1)

这对于TDD来说绝对有点过分。您希望使用TDD测试单元功能,并使用其他工具捕获更简单的错误。 (我只是担心,如果你开始在这个详细程度上编写测试,你将永远无法完成一个项目。)我个人认为refcounts不是单元界面的一部分,所以对我来说,它只是超出单元测试范围。

我建议使用仪器。运行所有测试并对它们进行检测(在OS X上,我们使用10.5之后的“Instruments”应用程序,在Linux上我们使用Valgrind)。检测将告诉您是否释放了所有对象或是否有内存泄漏。我还建议您确保测试错误路径 - 根据我的经验,当其他错误同时发生时,大多数内存泄漏都会发生。

我使用自定义测试脚本来运行所有测试,并且它有一个选项标记用于检测它们。我并不总是使用它们,因为完整的仪器级别会使测试速度变慢。

但是,如果你想以艰难的方式做事:

someProp = [[... alloc] init];
assert([someProp retainCount] == 1);
[myObject setSomeProp:someProp];
assert([someProp retainCount] > 1); // NOT == 2, that would be wrong
[myObject release];
assert([someProp retainCount] == 1);

为古老的Obj-C 1.0风格道歉。