回复中的沮丧情绪是压倒性的......但不要害怕,我们有the holy book to exorcise the demons of legacy C++ code。如果您已经排了一个多星期的时间与遗留 C++ 代码较量,请认真购买这本书。
转到第 127 页:可怕的包含依赖项的情况。(现在我什至离 Michael Feathers 几英里远,但我可以尽可能短地回答这个问题。。 )
问题:在 C++ 中,如果 classA 需要了解 ClassB,则 Class B 的声明是直接提升的/以文本形式包含在 ClassA 的源文件中。而且由于我们的程序员喜欢把它带到错误的极端,一个文件可以递归地包含无数其他的可传递文件。构建需要数年......但至少它会构建......我们可以等待。
现在说“在测试工具下实例化 ClassA 很困难”是轻描淡写的。 (引用 MF 的示例 - 调度程序是我们的海报问题孩子,拥有大量的依赖。)
#include "TestHarness.h"
#include "Scheduler.h"
TEST(create, Scheduler) // your fave C++ test framework macro
{
Scheduler scheduler("fred");
}
这将带出一连串构建错误的包含龙。
Blow#1 Patience-n-Persistence:一次处理每个包含一个,然后决定我们是否真的需要那个依赖。假设 SchedulerDisplay 是其中之一,其 displayEntry 方法在 Scheduler 的 ctor 中调用。
Blow#2 Fake-it-till-you-make-it(感谢 RonJ):
#include "TestHarness.h"
#include "Scheduler.h"
void SchedulerDisplay::displayEntry(const string& entryDescription) {}
TEST(create, Scheduler)
{
Scheduler scheduler("fred");
}
然后 pop 去依赖和它所有的传递包含。
您还可以通过将 Fake 方法封装在 Fakes.h 文件中以包含在您的测试文件中来重用 Fake 方法。
Blow#3 练习:它可能并不总是那么简单.. 但你明白了。在前几场决斗之后,破坏部门的过程将变得容易-n-机械
注意事项(我有提到有注意事项吗?:)
- 我们需要为这个文件中的测试用例单独构建;我们在一个程序中只能有一个 SchedulerDisplay::displayEntry 方法的定义。因此,为调度程序测试创建一个单独的程序。
- 我们不会破坏程序中的任何依赖项,因此我们不会使代码更简洁。
- 只要我们需要测试,您就需要维护这些假货。
- 你的审美可能会被冒犯一段时间..咬紧嘴唇,“和我们一起,共创美好明天”
将此技术用于具有严重依赖性问题的非常大的类。不要经常或轻率地使用.. 将此作为深入重构的起点。随着时间的推移,当您提取更多类(通过他们自己的测试)时,这个测试程序可以在谷仓后面进行。
更多..请阅读本书。无价。兄弟加油!