如何使用Google Test测试EXE?

Dmi*_*ruk 13 c++ googletest

我在Visual Studio中有一个C++项目,并且已经添加了另一个专门用于测试的项目.这两个项目都是EXE(控制台应用程序).那么如何在第二个项目中使用第一个项目呢?

只是为了澄清一下,如果第一个项目是一个可以简单地包含在第二个项目中的库,那么这里的问题就不言而喻了,但作为一个EXE,这就是问题所在.

Mik*_*han 35

根据您的意见,您有一个C++控制台应用程序(MyApp)为此您已经开发了一些特定于应用程序的类,您希望在Visual Studio中使用googletest进行单元测试.如何?

如你所说,如果你想对进行单元测试,那么这样做的方式就很明显了.你会:

  • 1)创建一个项目来创建一个单元测试应用程序(UnitTest).
  • 2)配置包含搜索目录,以便编译器可以找到库的头文件.
  • 3)配置库搜索目录,以便链接器可以找到库本身.
  • 4)将库本身添加到链接器输入.
  • 5)使UnitTest项目依赖于库项目,以便建筑物UnitTest确保MyApp是最新的.
  • 6)UnitTest根据googletest docs编写应用程序代码.

但是,由于您要进行单元测试的类是特定的MyApp,因此您没有任何库.

一个训练军士的回答是:你没有一个包含你要进行单元测试的类的库?所以做一个!

这样你就可以使用3个项目: -

  • MyAppLib,生成包含您要进行单元测试的所有功能的库.
  • MyApp,生成与目前相同的可执行文件,但链接 MyAppLib
  • UnitTest,生成单元测试MyAppLib,也链接的可执行文件MyAppLib

但是,如果你不喜欢训练中士的答案,你可以解决它.

从通常的构建系统角度(设计到Visual Studio中),MyApp项目的重要输出是构建目标 - .exe..obj生成的文件只是中间副产品.VS不支持将这些副产品作为依赖项目的自动链接器输入进行处理,并且如果依赖项目也是.exe同一类型 - 就像您的情况一样 - 那么无论如何这样的自动链接都是不可能的,因为主要的入口点将被多重定义.

但从单元测试的角度来看,情况恰恰相反.在.exe不感兴趣,而(部分)的.obj全部或部分文件包含您需要的类的实现进行单元测试.在foo定义foo.h和实现类的文本书案例中,链接中需要foo.cpp目标文件.foo.objUnitTest

为简单起见,假设只MyApp使用一个特定foo于应用程序的类,在其中定义foo.h和实现foo.cpp.然后你有两个建设选择UnitTest.

  • a)您可以添加foo.cpp到源文件中UnitTest.当然不要复制它.只需添加源文件夹中的现有项目MyApp.然后你就完成了,但是这个课程的缺点foo.cpp是在UnitTest项目中受到不适当的编辑.

  • b)您可以foo.obj像处理链接所需的静态库一样对待UnitTest并遵循上述步骤1) - 6).这尤其在步骤3)意味着{Debug | Release}构建UnitTest配置有包括\path\to\MyApp\{Debug|Release}(以相对或绝对形式)的库搜索目录.

实际上,对于选项b),很可能不止一个.obj文件MyApp需要链接UnitTest,很可能它们的数量会随着时间的推移而增长.保持正确的联系UnitTest可能会成为一件苦差事,你可能会得出结论,军士长毕竟是正确的.

  • 谢谢,我想我会咬紧牙关并重构为 LIB+EXE。 (2认同)

Ide*_*Hat 10

要看.Google Test(主要)是一个单元测试框架(过度简化,测试类).您可以绝对使用is进行其他类型的测试,但它没有"内置"功能用于其他类型的测试,您必须自己编写.

如果您尝试对可执行文件进行系统测试,则可以运行该过程.如果您使用的是多平台系统或已经具有提升依赖性,我建议使用Boost.Process.另外,看看这里:用stdin stdout和stderr启动一个exe /进程?

您编写的"测试"将调用可执行文件,并可以相应地输入stdin或stdout.

例如:

std::string path_to_exectuable = "thepath";
TEST(FooTester,CheckHelpScriptReturns0)
{
 using bp =::boost::process; 
 std::vector<std::string> args; args.push_back("--help");
 bp::context ctx; 
 ctx.stdout_behavior = bp::capture_stream(); 

 bp::child c = bp::launch(exec, args, ctx); 
 bp::status s = c.wait(); 
 ASSERT_TRUE(s.exited())<<"process didn't exit!";
 ASSERT_EQ(s.exit_status(),0)<<"Help didn't return 0";
}
Run Code Online (Sandbox Code Playgroud)