Xcode 中私有方法的单元测试

发布于 2024-07-26 16:01:02 字数 374 浏览 12 评论 0原文

我正在一个玩具项目中尝试测试驱动开发。 我可以让测试适用于我的类的公共接口(尽管我仍然持观望态度,因为我编写的测试代码比正在测试的方法中的测试代码多)。

我倾向于使用很多私有方法,因为我喜欢保持公共接口的干净; 但是,我仍然想对这些方法进行测试。

由于 Cocoa 是一种动态语言,我仍然可以调用这些私有方法,但我在测试中收到警告,我的类可能不会响应这些方法(尽管它显然会响应)。 因为我喜欢在没有警告的情况下进行编译,所以我的问题是:

  1. How do i close those warnings in Xcode?
  2. 我还可以采取其他措施来关闭这些警告吗?
  3. 我在尝试“白盒”测试时做错了什么吗?

I'm trying out test driven development in a toy project. I can get the tests working for the public interface to my classes (although I'm still on the fence because I'm writing more testing code than there is in the methods being tested).

I tend to use a lot of private methods becuase I like to keep the public interfaces clean; however, I'd still like to use tests on these methods.

Since Cocoa is a dynamic language, I can still call these private methods, but i get warnings in my tests that my class may not respond to these methods (although it clearly does). Since I like to compile with no warnings here are my questions:

  1. How do i turn off these warnings in Xcode?
  2. Is there something else I could do to turn off these warnings?
  3. Am I doing something wrong in trying 'white box' testing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

云胡 2024-08-02 16:01:03

请记住,Objective-C 中实际上不存在“私有方法”之类的东西,这不仅仅是因为它是一种动态语言。 按照设计,Objective-C 具有 ivars 的可见性修饰符,但没有针对方法的可见性修饰符 — 您可以调用任何您喜欢的方法,这并非偶然。

@Peter的建议很好。 为了补充他的答案,我使用的另一种选择(当我不想/只需要私有方法的标头时)是在单元测试文件本身中声明一个类别。 (我使用 @interface MyClass (Test) 作为名称。)这是添加在发布代码中不必要的方法的好方法,例如用于访问被测试类具有的 ivars进入。 (当使用属性时,这显然不是一个问题。)

我发现这种方法可以轻松公开和验证内部状态,以及添加仅测试方法。 例如,在这个单元测试文件中,我编写了一个< code>-isValid 方法用于验证二进制堆的正确性。 在生产中,这种方法会浪费空间,因为我假设堆是有效的 - 如果我修改代码,我只在测试单元测试回归时才关心它。

Remember that there's actually no such thing as "private methods" in Objective-C, and it's not just because it's a dynamic language. By design, Objective-C has visibility modifiers for ivars, but not for methods — it's not by accident that you can call any method you like.

@Peter's suggestion is a great one. To complement his answer, an alternative I've used (when I don't want/need a header just for private methods) is to declare a category in the unit test file itself. (I use @interface MyClass (Test) as the name.) This is a great way to add methods that would be unnecessary bloat in the release code, such as for accessing ivars that the class under test has access to. (This is obviously less of an issue when properties are used.)

I've found this approach makes it easy to expose and verify internal state, as well as adding test-only methods. For example, in this unit test file, I wrote an -isValid method for verifying correctness of a binary heap. In production, this method would be a waste of space, since I assume a heap is valid — I only care about it when testing for unit test regressions if I modify the code.

ゃ懵逼小萝莉 2024-08-02 16:01:03

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

不。

我还可以采取其他措施来关闭这些警告吗?

不。

我在尝试“白盒”测试时做错了什么吗?

不。

解决方案是将您的私有方法移至其自己标头中的类别。 将此标头导入到实际类和测试用例类实现文件中。

How do i turn off these warnings in Xcode?

Don't.

Is there something else I could do to turn off these warnings?

Don't.

Am I doing something wrong in trying 'white box' testing?

No.

The solution is to move your private methods to a category in its own header. Import this header into both the real class and test-case class implementation files.

天涯沦落人 2024-08-02 16:01:03

看起来另一个问题有答案: 有没有办法抑制Xcode 中出现警告?

Looks like another question has the answer: Is there a way to suppress warnings in Xcode?

桜花祭 2024-08-02 16:01:03

几天前,当我开始使用 TDD 时,我也遇到了同样的问题。 我在 测试驱动的 iOS 开发 中发现了这个非常有趣的观点书:

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

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

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

I was dealing with the same issue when I started with TDD few days ago. I've found this very interesting point of view in Test-Driven iOS Development book:

I have often been asked, “Should I test my private methods?” or the related question “How should I test my private methods?” People asking the second question have assumed that the answer to the first is “Yes” and are now looking for a way to expose their classes’ private interfaces in their test suites.

My answer relies on observation of a subtle fact: You already have tested your private methods. By following the red–green–refactor approach common in test-driven development, you designed your objects’ public APIs to do the work those objects need to do. With that work specified by the tests—and the continued execution of the tests assuring you that you haven’t broken anything—you are free to organize the internal plumbing of your classes as you see fit.

Your private methods are already tested because all you’re doing is refactoring behavior that you already have tests for. You should never end up in a situation where a private method is untested or incompletely tested, because you create them only when you see an opportunity to clean up the implementation of public methods. This ensures that the private methods exist only to support the class’s that they must be invoked during testing because they are definitely being called from public methods.

高速公鹿 2024-08-02 16:01:03

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

While having a private header or defining your own category are probably more correct solutions there is also another very simple solution: cast the object to (id) before calling the method.

悟红尘 2024-08-02 16:01:03

如果您不想将私有方法实现分布在多个源文件中,则对类别解决方案的改进是定义一个扩展(本质上是一个匿名类别 - 请参阅 Apple 文档)位于由现有类的实现和相关单元导入的头文件中测试源文件。

如果主 @implementation 块中不存在私有方法的实现,则使用扩展可以让编译器发出警告。 此链接很好地说明了这一点。

If you don't want to distribute your private method implementations across multiple source files, a refinement to the Category solution is to define an Extension (essentially an anonymous Category - refer to Apple's documentation) in a header file that's imported by both your existing class' implementation and the relevant unit test source files.

Using an Extension allows the compiler to warn you if the implementation of the private method is not present in the main @implementation block. This link illustrates it nicely.

鼻尖触碰 2024-08-02 16:01:03

轻松的工作。 脚步:
1. 你有 -(NSString*)getTestString; 在接口 Foo 的目标 m 文件中

  1. 在单元测试文件中添加一个类别:

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

然后,现在就做任何你想做的事。

Easy Job. Steps:
1. You have -(NSString*)getTestString; in your target m file for interface Foo

  1. Add a category in your unit test file:

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

Then, do anything you want now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文