这是我进行TDD编程的方式。首先,我确定需要添加的新功能,然后确定该功能将具有的所有外部依赖项。例如,我的当前项目中存在对C API的依赖,该API提供有关我正在使用的模型的信息。我还依赖于命令行,因为客户端可以输入命令,我必须做出响应。这个命令行是通过一个特殊的终端实现的,但我不关心它的详细信息。
因此,我为这些外部依赖项创建接口类,然后在我的代码中只使用这些接口。结果是,在进行测试时,我不需要模型的C++库或终端的C++库(稍后会详细介绍)。以下是用于向命令行写入的接口示例:
class ICommandLineOutput
{
public:
virtual void WriteLine(std::string&) = 0;
};
假设我被要求编写一个类,将时间写入命令行,称为WriteTime。那么,我将在这个类的构造函数中传递一个类型为ICommandLineOutput的对象,并仅使用此接口进行工作。我不关心我正在使用哪种类型的命令行,只关心它的接口。只要它以ICommandLineOutput类为基础,我就可以使用任何命令行类。
class WriteTime
{
public:
explicit WriteTime(ICommandLineOutput commandLine): _commandLine(commandLine){}
...
};
在进行单元测试时,我会有一个单独的C++项目,用于测试我编写的每个类。这个项目可以使用Google Test,并且可以是一个命令行项目。因此,即使您正在编写包含在GUI C++项目中的GUI应用程序,测试也有自己的项目。
假设我想测试写入命令行的类。我将在名为TestWriteTime的类中执行此操作。我将使用GoogleMock创建ICommandLineOutput接口的模拟。然后可以在测试基础上对模拟进行询问和/或配置,以确定WriteTime是否按预期运行。例如,我可以检查调用WriteLine()的次数以及它接收的参数。
最后,在我的当前项目中,我正在使用具有大量依赖项的基于Linux的项目。该应用程序启动时间也很长。但是,我有一个Windows控制台项目,用于进行测试。这个应用程序在不到一秒钟的时间内执行,非常适合TDD。