使用测试类而不是通常使用的类来测试 C++ 程序

Posted

技术标签:

【中文标题】使用测试类而不是通常使用的类来测试 C++ 程序【英文标题】:Testing C++ program with Testing classes over normally used classes 【发布时间】:2010-04-07 11:57:35 【问题描述】:

这可能是一个无意义的问题,但我会尽力而为。

我有一个简单的 c++ 程序,我需要为其构建测试。除了我实际使用的类之外​​,我还有 2 个类,它们称为 WebServer 和 BusinessLogicLayer。

为了测试我自己的代码,我制作了这些类的我自己的版本,这些版本向我的类提供虚拟数据以测试它的功能。

我需要知道一种方法,例如通过生成文件,如何告诉源代码使用测试类而不是通常使用的类。测试类位于不同的“tester”c++ 文件中,而tester c++ 文件也有自己的头文件。

问候

保罗

附:这可能是一个措辞不好的问题,但我不知道有什么更好的方式来提出我的问题。

【问题讨论】:

【参考方案1】:

您可以定义为组件声明公共接口的抽象基类,然后在运行时将对象连接在一起(在main() 或食物链中相当高的位置)。在测试中,您只需连接不同的对象。

【讨论】:

在运行时“连接”不同的对象并非易事。在堆栈上构建 WebServer 或 BusinessLogicLayer 的任何地方都需要重新编码(我承认这些类不应该有很多地方)。如果您在较高级别做出决定(例如在 main() 中),那么您必须以某种方式将其传递给需要它的类。 WebServer 和 BusinessLogicLayer 可能是您不希望同时拥有真实和虚假版本的东西,这意味着您正在“连接”类,而不是对象。如果它们必须在 main() 执行之前构建(例如静态对象)......不是微不足道的。 您可以使用单例接口声明 WebServer。 main() 负责创建适当的派生类实例并将其分配为要返回的单例。想要与 WebServer 交互的代码只需访问单例 API。这是单例的少数有效用途之一。 如果 WebServer 和 BusinessLogicLayer 都可以是单例的,那么您就可以摆脱这个问题。但是,您不能将任何静态成员初始化为指向或引用它们(这是很自然的事情)现在或将来的代码修订版。此外,任何想要构建工作版本的人也必须拥有测试代码,否则链接将失败。而且此方法不可扩展至您的其他非单例类。 是的,有单身人士的陷阱。当然,使用单例的方法不止一种。您可以改为将工厂类定义为单例,从而允许代码库根据需要实例化任意数量的 WebServer,而不依赖于静态数据,同时仍将其留给 main() 来决定将创建哪个 WebServer 派生类。 【参考方案2】:

使用目录 $SRC_DIR_1 和 $SRC_DIR_2 中的源代码构建程序的调试和发布版本:

CXX      := g++
CPPFLAGS  = ...
CXXFLAGS  = ...

SRC_DIR_1 := ...
SRC_DIR_2 := ...

ifeq ($debug,1)
  BIN_DIR  := ./obj_debug
  CXXFLAGS += -g
else
  BIN_DIR  := ./obj_release
  CXXFLAGS += -DNDEBUG
endif

# Make sure that the directory exists.
TEMP := $shell test -d $BIN_DIR || mkdir $BIN_DIR

# Tell make to search each directory
VPATH := $SRC_DIR_1:$SRC_DIR_2

# You can modify this to use a suffix other than .cc
$BIN_DIR/%.o : %.cc
    $CXX $CPPFLAGS $CXXFLAGS -c $< -o $@

# Build the requested version of the program.
ifeq ($debug,1)
  default: program_name_debug
else
  default: program_name
endif

tidy::
    @$RM -r ./obj_*

在“项目配置”对话框中,将目标名称指定为“program_name, program_name_debug”。 (将 program_name 替换为您的程序名称。)

要构建程序,调用“make debug=X”,将 X 替换为 0 或 1。

Reference

【讨论】:

【参考方案3】:

为什么您的测试代码有自己的头文件?您的测试代码应该与它模拟的代码具有相同的接口,并且使用相同的头文件可以避免很多麻烦。

无论如何,这将起作用:

real_program: WebServer.o BusinessLogicLayer.o

test_program: tester.o

real_program test_program: MyClass.o OtherThings.o
    $(LINK) $^ -o $@

【讨论】:

以上是关于使用测试类而不是通常使用的类来测试 C++ 程序的主要内容,如果未能解决你的问题,请参考以下文章

如何显示使用类而不是Gradle Suite的报表门户启动?

Python之自动单元测试之一(unittest使用实例)

如何使用 C++ 中的类创建和填充链表?

Gtest:参数化

C++:动态 .so 库中的类

使用来自另一个 MEF 程序集的类而不引用它