我对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")
有什么建议吗? 谢谢!
答案 0 :(得分:4)
假设您可以执行上述操作,您实际会测试什么?这就是我的想法:
测试-release会减少retainCount
测试当retainCount达到零时NSObject的垃圾收集机制调用-dealloc
测试当调用-dealloc时,myProperty被释放
这是单元测试的错误粒度,第一点和第二点不是您要测试的业务 - 假设它是由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风格道歉。