2009-07-08 136 views
61

我正在尝试玩具项目中的测试驱动开发。我可以将测试工作用于我的类的公共接口(尽管我仍在编程,因为我正在编写比测试方法中更多的测试代码)。Xcode中私有方法的单元测试

我倾向于使用很多私有方法,因为我喜欢保持公共接口清洁;不过,我仍然想使用这些方法的测试。

由于可可是一种动态语言,我仍然可以调用这些私有方法,但我在我的测试中,我的类可能不会对这些方法的响应得到警告(虽然它显然不会)。由于我喜欢编译没有警告,这里是我的问题:

  1. 我如何关闭这些在Xcode中的警告?
  2. 还有什么我可以做的关掉这些警告?
  3. 我在做'白盒'测试时做错了什么?
+0

到目前为止,我还没有在头文件中公开我的私有方法。为什么我应该在头文件中使用公共方法更优雅呢?但是,似乎我必须在objective-c中改变这一点。 – Nils 2012-01-10 13:01:38

+1

@Nils头文件中没有私有方法。一旦到达,它们就是公共方法。 – Abizern 2012-01-10 13:35:16

+0

是@Abizern到目前为止,我遵循了下面的Peter Hosey的建议。 – Nils 2012-01-10 13:43:16

回答

88

我如何关闭在Xcode这些警告?

不要。

还有什么我可以做的关掉这些警告?

不要。

我做得不对,试图“白盒”测试?

解决的办法是你的私有方法移动到它自己的头一个类别。将此头文件导入真实类和测试用例类实现文件。

+4

+1 - 伟大的建议!有关详细信息,请参阅此问题/答案:http://stackoverflow.com/questions/1020070/#1020330例如,包含具有私有方法的类别的私有头文件可以命名为MyClass_Private.h。 – 2009-07-08 16:36:30

+2

感谢您的回答。我仍然不确定,但我必须承认,编写测试然后通过测试是有趣的。 – Abizern 2009-07-09 10:58:17

4

看起来像另一个问题有了答案:Is there a way to suppress warnings in Xcode?

+1

这是答案的一部分,但对于某个特定案例来说最好的(或至少是更完整的)解决方案可能与Peter的答案或我的答案有关。 – 2009-07-08 17:15:05

+0

这也不是放置重复链接的地方。 – Rambatino 2014-10-08 17:37:39

124

请记住,在Objective-C中实际上没有“私有方法”这样的事情,而且这不仅仅是因为它是一种动态语言。通过设计,Objective-C为ivars提供了可见性修饰符,但不是用于方法的 - 您可以调用任何您喜欢的方法并非偶然。

@Peter的建议是一个伟大的。为了补充他的答案,我使用的一个替代方案(当我不想/只需要一个头部用于私人方法时)是在单元测试文件本身中声明一个类别。 (我使用@interface MyClass (Test)作为名称)。这是一种添加方法的好方法,这些方法在发布代码中不必要的膨胀,比如访问受测试类可以访问的ivars。 (这显然是不成问题的性质使用时)。

我发现这种方法可以很容易地揭露和证实的内部状态,以及添加唯一的测试方法。例如,在this unit test file中,我写了一个-isValid方法来验证二进制堆的正确性。在生产中,这种方法会浪费空间,因为我认为堆是有效的 - 如果我修改代码,在测试单元测试回归时我只关心它。

3

虽然拥有私人头文件或定义自己的类别可能是更正确的解决方案还有另一个非常简单的解决方案:在调用方法之前将对象强制转换为(id)。

3

如果您不想在多个源文件中分发您的私有方法实现,对Category解决方案的改进是在两个导入的头文件中定义一个扩展(实质上是一个匿名类别 - 参见Apple's documentation)你现有的类的实现和相关的单元测试源文件。

使用扩展允许编译器在主@implementation块中不存在私有方法的实现时发出警告。 This link很好地说明了这一点。

3

几天前我开始使用TDD时,我正在处理同样的问题。我发现这非常有趣的观点在Test-Driven iOS Development书:

我经常被问,“我应该测试我的私有方法?”或相关的问题:“我应该如何测试我的私有方法?”的人问第二个问题假定第一个答案是“是”,现在正在寻找一种方法在他们的测试套件中公开他们的类的私有接口。

我的答案依赖于观察一个微妙的事实:您已经测试了您的私有方法。通过遵循测试驱动开发中常见的红绿重构方法,您设计了对象的公共API来完成这些对象需要执行的工作。通过测试指定的工作 - 并继续执行测试,确保您没有破坏任何东西 - 您可以自由组织班级的内部管道,只要您认为合适。

您的私有方法已经过测试,因为您所做的只是您已经进行过测试的重构行为。在私有方法未经测试或未完全测试的情况下,您绝不应该因为只有在您看到清理公共方法实现的机会时才创建它们。这确保了私有方法的存在只是为了支持在测试期间必须调用的类,因为它们肯定是从公共方法调用的。

0

简单的工作。步骤: 1.你有 - (NSString *)getTestString;在接口的Foo目标米文件

  • 添加类别在单元测试文件:

    @interface DemoHomeViewController() - (的NSString *)getTestString; @end

  • 然后,做任何你想要的东西。