我已经阅读了这篇关于如何测试私有方法的文章。我通常不测试它们,因为我总是认为只测试将从对象外部调用的公共方法更快。你测试私有方法吗?我应该一直测试它们吗?
当前回答
如果你的私有方法没有通过调用公共方法来测试,那么它在做什么? 我说的是私人的,不是受保护的,也不是朋友。
其他回答
正如上面引用的,“如果你不测试你的私有方法,你怎么知道它们不会崩溃?”
这是一个大问题。单元测试的一个重要要点是尽快知道在哪里、何时以及如何发生故障。这样就减少了大量的开发和QA工作。如果所有测试的都是公开的,那么您就没有对类的内部进行诚实的覆盖和描述。
我发现最好的方法之一是将测试引用添加到项目中,并将测试放在与私有方法并行的类中。放入适当的构建逻辑,这样测试就不会构建到最终项目中。
然后,您就有了测试这些方法的所有好处,您可以在几秒钟内而不是几分钟或几小时内发现问题。
总之,单元测试你的私有方法。
对于从测试中调用什么api,公共和私有并不是一个有用的区分,方法和类也不是。大多数可测试单元在一个上下文中是可见的,但在其他上下文中是隐藏的。
重要的是覆盖范围和成本。您需要最小化成本,同时实现项目的覆盖目标(行、分支、路径、块、方法、类、等价类、用例……)不管团队怎么决定)。
因此,使用工具来确保覆盖率,并设计您的测试以减少成本(短期和长期)。
不要让测试变得过于昂贵。 如果只测试公共入口是最便宜的,那就这样做。 如果测试私有方法成本最低,那就这么做。
随着您的经验越来越丰富,您将能够更好地预测何时值得重构以避免测试维护的长期成本。
当我在我们的项目中越来越多地遵循我们最新的QA建议时,我感觉有必要测试私有函数:
每个函数圈复杂度不超过10。
现在,执行这项政策的副作用是,我的许多非常大的公共职能被划分为许多更集中的,更好地命名为私人职能。 公共功能仍然存在(当然)但本质上被简化为所有那些私人的“子功能”
这实际上很酷,因为调用堆栈现在更容易阅读(而不是一个大函数中的bug,我在一个子子函数中有一个bug,它具有调用堆栈中先前函数的名称,以帮助我理解“我是如何到达那里的”)
然而,现在似乎更容易直接对那些私有函数进行单元测试,而将大型公共函数的测试留给某种需要解决场景的“集成”测试。
这只是我的个人意见。
我认为单元测试是用来测试公共方法的。您的公共方法使用您的私有方法,因此它们也间接地接受测试。
是的,您应该在任何可能的地方测试私有方法。为什么?避免不必要的测试用例状态空间爆炸,最终只是在相同的输入上隐式地重复测试相同的私有函数。让我们用一个例子来解释为什么。
考虑一下下面略显做作的例子。假设我们想公开一个函数,该函数接受3个整数,当且仅当这3个整数都是素数时返回true。我们可以这样实现它:
public bool allPrime(int a, int b, int c)
{
return andAll(isPrime(a), isPrime(b), isPrime(c))
}
private bool andAll(bool... boolArray)
{
foreach (bool b in boolArray)
{
if(b == false) return false;
}
return true;
}
private bool isPrime(int x){
//Implementation to go here. Sorry if you were expecting a prime sieve.
}
现在,如果我们采取严格的方法,只测试公共函数,我们只允许测试allPrime,而不允许测试isPrime或andAll。
作为测试人员,我们可能对每个参数的五种可能性感兴趣:< 0,= 0,= 1,质数> 1,而不是质数> 1。但为了彻底,我们还必须看看每个参数的组合是如何发挥作用的。根据我们的直觉,我们需要5*5*5 = 125个测试用例来彻底测试这个函数。
On the other hand, if we were allowed to test the private functions, we could cover as much ground with fewer test cases. We'd need only 5 test cases to test isPrime to the same level as our previous intuition. And by the small scope hypothesis proposed by Daniel Jackson, we'd only need to test the andAll function up to a small length e.g. 3 or 4. Which would be at most 16 more tests. So 21 tests in total. Instead of 125. Of course, we probably would want to run a few tests on allPrime, but we wouldn't feel so obliged to cover exhaustively all 125 combinations of input scenarios we said we cared about. Just a few happy paths.
当然,这是一个虚构的例子,但为了清晰地演示,这是必要的。这种模式可以扩展到真实的软件中。私有函数通常是最低级别的构建块,因此经常组合在一起以产生更高级别的逻辑。也就是说,在较高的层次上,由于不同的组合,我们对较低层次的东西有更多的重复。
推荐文章
- 为什么Visual Studio 2015/2017/2019测试运行器没有发现我的xUnit v2测试
- 单元测试反模式目录
- ReferenceError: description没有定义NodeJs
- 类未找到:IntelliJ中的空测试套件
- Mockito的argumentCaptor的例子
- 单元测试:日期时间。现在
- 为什么单元测试中的代码不能找到包资源?
- 你能解释一下流的概念吗?
- 存在类型是什么?
- 从导入的模块中模拟函数
- 在单元测试中设置HttpContext.Current.Session
- 编程中的术语“上下文”?
- 何时使用Mockito.verify()?
- 在PHP单元测试执行期间,如何在CLI中输出?
- 单元测试的一些常用命名约定是什么?