C++ 通过使私有方法成为自由函数来进行单元测试
在2017年cppcon的视频中,我看到了克劳斯·伊尔贝格的一篇演讲,题目是“”。 在这次演讲中,演讲者谈到了如何切换到自由功能 简化测试私有方法的过程(参见19:00)。这个想法是你拉着 私有方法脱离类(您使其成为一个自由函数),它成为可测试的 起初,我觉得这个想法很有趣,但后来 我想得越多,就越不明白这到底是怎么回事。例如 假设我有以下(虚拟)类: 然后C++ 通过使私有方法成为自由函数来进行单元测试,c++,unit-testing,private-methods,non-member-functions,C++,Unit Testing,Private Methods,Non Member Functions,在2017年cppcon的视频中,我看到了克劳斯·伊尔贝格的一篇演讲,题目是“”。 在这次演讲中,演讲者谈到了如何切换到自由功能 简化测试私有方法的过程(参见19:00)。这个想法是你拉着 私有方法脱离类(您使其成为一个自由函数),它成为可测试的 起初,我觉得这个想法很有趣,但后来 我想得越多,就越不明白这到底是怎么回事。例如 假设我有以下(虚拟)类: 然后someComplexTask()和someOtherComplexTask()是私有方法。这意味着他们 是实现细节,即它们只能在SomeC
someComplexTask()
和someOtherComplexTask()
是私有方法。这意味着他们
是实现细节,即它们只能在SomeClass
(或friends)中调用。信息技术
在我看来,如果你让它们成为自由函数,是的,它们是可测试的,但它们不再是
私有,而不仅仅是特定于SomeClass
的实现细节。事实上,它们可以从代码中的任何地方调用
所以我的问题是:为什么伊格伯格先生的观点是正确的?我也看过这段视频。但是,我有一些不同意见 1-您的方法是否需要访问字段?如果不是,则它不属于该类。但如果是这样,他们就需要田地。自由函数无权访问字段,除非您将其作为函数参数传递。请考虑自由功能不应被视为公共功能。 2-并不是所有的东西都应该是自由函数。但这是一个很好的做法,避免在不必要的时候把所有东西都放在课堂上 3-私人功能通常不需要测试。但是如果您坚持,您可能能够执行诸如无效黑客(这并不总是像评论中提到的那样有效)之类的操作: 释放你的功能更简洁,但不是更可行 这清楚地表明您存在设计缺陷。如果你有 你需要测试的私有函数,你必须向后弯曲 如果要让它工作,那么就有问题了。你错过了什么。 你的设计不起作用 他的观点不仅仅是让私人功能免费。他并不是说:“获得你所有的私人功能,让它们成为自由功能”。他说需要测试的功能不应该是一个实现细节,因为如果你需要测试它,这表明该功能是有用的 请密切注意他对代码所做的转换: 初始代码:
class X
{
public:
void doSomething( ... ) {
...
resetValues();
...
}
...
private:
void resetValues() {
for( int& value : values_ )
value = 0;
}
std::vector<int> values_;
};
现在,resetValues
是一项可以重用和测试的功能。由于它确实与X
无关,但通过重置向量的所有值,使其成为自由函数而不是私有X
方法是一种有效的设计
我喜欢Rann Lifshitz在评论中所说的:
我认为更好的方法是了解一些私人 实际上,函数是公共效用函数
如果有人决定在这里观看视频,这是一个准确的答案time@smac89谢谢,我用你的链接更新了我的问题。我认为这完全取决于那些私有方法的使用。在该视频中,他使用的示例可以很容易地转化为自由函数,因为它的用途非常通用,不依赖于类中的任何内容。我不会从字面上理解那个视频。我认为关键是,您应该能够在代码中找到自由函数与成员函数一样工作的地方,因为自由函数更容易测试。拥有一个私有的重置方法,它可以变成一个可测试的重置(免费)函数,这是一个糟糕的设计。我想他建议的是,将你希望测试的私有函数重构为实用类中的公共函数。在我看来,这仍然比类标题中的自由函数的概念好,但这只是我的拙见。如果你在发布几秒钟后解释你不喜欢这个答案的原因,那就太好了。哦,天哪,不!你做了什么?只需使用适当的测试框架。不要这样做。这里所说的定义正是Klaus Iglberger所说的设计突破解决方案。定义C++关键词是非法的。@ ARASH NO.CUDATABASE <代码>描述了一个有效代码(从标准的角度),使用了一些反模式或是不可读取的,不可维护的等等。你有非法的C++代码。我认为最好的方法是理解一些私有函数实际上是通用效用函数,应该在通用工具类中公开。对我来说,这种方法听起来比使用自由函数要好得多,自由函数是OOP领域中一只奇怪的鸟。@RannLifshitz:“通用实用程序类中应该是公共的公共实用程序函数”-实用程序名称空间比类更合适,对于不共享数据或职责的函数:它们将逻辑分组与头文件分离,并且(通常是好是坏)让客户机程序员可以自由决定是否使用名称空间或特定函数,或者在客户机代码中保持它们的显式性。
#define class struct
#define private public
#define protected public
#include "library.h"
#undef class
#undef private
#undef protected
class X
{
public:
void doSomething( ... ) {
...
resetValues();
...
}
...
private:
void resetValues() {
for( int& value : values_ )
value = 0;
}
std::vector<int> values_;
};
void resetValues( std::vector<int>& vec )
{
for( int& value : vec )
value = 0;
}