我已经阅读了这篇关于如何测试私有方法的文章。我通常不测试它们,因为我总是认为只测试将从对象外部调用的公共方法更快。你测试私有方法吗?我应该一直测试它们吗?


当前回答

是的,我确实测试私有函数,因为尽管它们是由你的公共方法测试的,但在TDD(测试驱动设计)中测试应用程序的最小部分是很好的。但是在测试单元类中不能访问私有函数。下面是我们测试私有方法的方法。

为什么我们有私有方法?

私有函数主要存在于我们的类中,因为我们希望在公共方法中创建可读的代码。 我们不希望这个类的用户直接调用这些方法,而是通过我们的公共方法。此外,我们不希望在扩展类时改变它们的行为(在受保护的情况下),因此它是一个private。

当我们编码时,我们使用测试驱动设计(TDD)。这意味着有时我们会偶然发现一个私有的功能片段并想要进行测试。私有函数在phpUnit中是不可测试的,因为我们不能在Test类中访问它们(它们是私有的)。

我们认为有3个解决方案:

1. 你可以通过你的公共方法来测试你的私处

优势

简单的单元测试(不需要“hack”)

缺点

程序员需要了解公共方法,而他只想测试私有方法 您不是在测试应用程序中最小的可测试部分

2. 如果private是如此重要,那么为它创建一个新的单独的类可能是一个代码味道

优势

你可以把它重构成一个新类,因为如果是这样的话 重要的是,其他类可能也需要它 可测试单元现在是一个公共方法,因此可测试

缺点

如果一个类是不需要的,并且只被 方法来自的类 由于增加的开销而造成潜在的性能损失

3.将访问修饰符更改为(final) protected

优势

您正在测试应用程序中最小的可测试部分。当 使用final protected,函数将不会被重写(只是 像一个私人) 无性能损失 没有额外的开销

缺点

你把一个私有访问权限改成了受保护,也就是说 它的孩子可以接触到 您仍然需要在测试类中使用Mock类

例子

class Detective {
  public function investigate() {}
  private function sleepWithSuspect($suspect) {}
}
Altered version:
class Detective {
  public function investigate() {}
  final protected function sleepWithSuspect($suspect) {}
}
In Test class:
class Mock_Detective extends Detective {

  public test_sleepWithSuspect($suspect) 
  {
    //this is now accessible, but still not overridable!
    $this->sleepWithSuspect($suspect);
  }
}

因此,我们的测试单元现在可以调用test_sleepWithSuspect来测试之前的私有函数。

其他回答

我认为最好只测试对象的公共接口。从外部世界的角度来看,只有公共接口的行为是重要的,这是您的单元测试应该指向的方向。

一旦你为一个对象编写了一些可靠的单元测试,你就不希望因为接口背后的实现改变了而不得不回去修改那些测试。在这种情况下,您已经破坏了单元测试的一致性。

我认为单元测试是用来测试公共方法的。您的公共方法使用您的私有方法,因此它们也间接地接受测试。

测试的目的是什么?

到目前为止,大多数答案都说私有方法是实现细节,只要公共接口经过良好测试并能够正常工作,这些实现细节就不重要(至少不应该)。如果测试的唯一目的是保证公共接口正常工作,那么这是绝对正确的。

就我个人而言,我对代码测试的主要用途是确保将来的代码更改不会导致问题,并且在出现问题时帮助我进行调试。我发现对私有方法的测试就像对公共接口的测试一样彻底(如果不是更彻底的话!),可以进一步达到这个目的。

考虑:您有一个公共方法A,它调用私有方法B。A和B都使用方法C。C被更改(可能由您更改,也可能由供应商更改),导致A开始测试失败。对B进行测试不是很有用吗,即使它是私有的,这样你就知道问题是在A使用C, B使用C,还是两者都有?

Testing private methods also adds value in cases where test coverage of the public interface is incomplete. While this is a situation we generally want to avoid, the efficiency unit testing depends both on the tests finding bugs and the associated development and maintenance costs of those tests. In some cases, the benefits of 100% test coverage may be judged insufficient to warrant the costs of those tests, producing gaps in the public interface's test coverage. In such cases, a well-targeted test of a private method can be a very effective addition to the code base.

正如上面引用的,“如果你不测试你的私有方法,你怎么知道它们不会崩溃?”

这是一个大问题。单元测试的一个重要要点是尽快知道在哪里、何时以及如何发生故障。这样就减少了大量的开发和QA工作。如果所有测试的都是公开的,那么您就没有对类的内部进行诚实的覆盖和描述。

我发现最好的方法之一是将测试引用添加到项目中,并将测试放在与私有方法并行的类中。放入适当的构建逻辑,这样测试就不会构建到最终项目中。

然后,您就有了测试这些方法的所有好处,您可以在几秒钟内而不是几分钟或几小时内发现问题。

总之,单元测试你的私有方法。

如果你的私有方法没有通过调用公共方法来测试,那么它在做什么? 我说的是私人的,不是受保护的,也不是朋友。