如何着手组织遗留 Visual C++ 的单元测试工具 代码?
我有一个 Visual Studio 2005 C++ 项目,它是一个控制台应用程序。
我想开始在测试工具下获取部分代码,但我遇到了一些我不知道如何最好处理的问题。
我不希望我的大部分测试代码最终出现在生产中的正常 .exe 中,因此我认为最好为我的测试创建一个单独的项目。 第一个问题,这个新项目将如何调用其余代码? 我是否应该将遗留代码设为具有单个入口点的 .lib 或 .dll,并创建一个单独的项目来调用遗留代码的主要部分?
我是否应该采取丑陋的做法,将所有测试放入完全是 #ifdef TESTING
的文件中,这样代码就不会出现在我的生产 .exe 中? 如果是这样,我应该如何有条件地加载我的测试框架? 使用单独的属性配置进行测试?
我基本上正在寻找有关如何在 Visual C++ 中的旧 .exe 项目上获取测试工具的任何建议
I have a Visual Studio 2005 C++ project, it is a console application.
I want to start getting bits of the code under a test harness but I've run into some issues that I don't know how to best handle.
I don't want most of my testing code to end up in the normal .exe in production so I thought would be best to create a separate project for my tests. First issue, how is this new project going to call into the rest of the code? Should I make my legacy code a .lib or .dll with a single entry point and create a separate project that calls the main of my legacy code?
Should I go for the ugly hack of putting all my tests in files that are entirely #ifdef TESTING
so that the code doesn't end up in my production .exe? If so how should I conditionally load my testing framework? Use a separate Properties Configuration for testing?
I'm basically looking for any suggestions on how to go about getting a test harness on a legacy .exe project in Visual C++
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,我强烈推荐 Michael Feather 的书“有效处理遗留代码”。 这都是关于如何向没有测试的遗留应用程序添加自动化单元测试。 如果您想知道“我如何开始测试这堆代码”,那么这本书就适合您。
Michael 也是 CppUnit 的作者,CppUnit 是一个用于 C++ 代码的类似 NUnit 的开源测试框架。 您可以在这里找到它:http://sourceforge.net/projects/cppunit/。
添加测试的一种快速而简单的方法是将 UnitTest 配置添加到您的解决方案中。 此配置将编译您的代码,但不是将其链接到 main.CPP,而是从构建中排除 main.cpp 并包含 UnitTestMain.cpp,您将在其中放置调用以执行单元测试。 很久以前,当我们不知道更好的时候,我们就开始这样做了。 不过,您最终会花费大量时间在各种配置中包含和排除所有不同的 testMyCode.cpp 模块,并且在一段时间后会变得很累。 我们发现开发人员不太喜欢这种方法。
更好的方法是将单元测试项目添加到您的解决方案中,并构建依赖于您的实际项目。 如果项目名为 Foo.vcproj,则将其命名为 Foo_test.vcproj。 该项目仅包含您的测试代码,它 #includes 您的 Foo 标头,并且链接到您编译的 fooCode.obj 模块。 添加对执行 Foo_test.exe 的调用作为 Foo_test 构建的构建后步骤,并在构建期间自动运行单元测试。 如果任何单元测试失败,构建就会失败。 如果您在构建服务器上配置了门控签入,则没有人可以签入破坏现有测试的更改。
First, I'd strongly recommend Michael Feather's book "Working Effectively with Legacy Code". It's all about how to add automated unit tests to a legacy app that has no tests. If you're wondering "how do I even start testing this pile of code" then this book is for you.
Michael is also the author of CppUnit, an Open Source NUnit-like testing framework for C++ code. You can find it here: http://sourceforge.net/projects/cppunit/.
One quick-and-dirty way to add tests is to add a UnitTest configuration to your solution. This configuration would compile your code, but instead of linking it to your main.CPP, you exclude your main.cpp from the build and include UnitTestMain.cpp, where you would place the calls to execute the unit tests. We started out this way a long time ago, when we didn't know any better. You end up spending a lot of time including and excluding all the various testMyCode.cpp modules to the various configurations, though, and it gets tiring after a while. We found that developers didn't like that approach too much.
A much better approach is to add a unit test project to your solution, with a build dependency upon your real project. If the project is named Foo.vcproj, call it Foo_test.vcproj. This project contains just your test code, it #includes your Foo headers, and it links to your compiled fooCode.obj modules. Add a call to execute Foo_test.exe as a post-build step of the Foo_test build, and it automatically runs the unit tests during the build. If any unit tests fail, the build fails. If you have gated-check-ins configured on your build server, nobody can check in changes that break existing tests.
我认为将大部分经过测试的代码放在库中是最好的,但不一定在所有情况下都实用。
一种解决方案是使用单独的项目配置(例如,调试、发布和测试),并将测试代码放在单独的文件中,这些文件在调试和发布配置下标记为“从构建中排除”。 您可以使用简单的代码在
#ifdef
中启动测试,也可以使用非测试版本中包含的测试运行程序的存根版本。另一种选择(尽管它相当 hack-ish)是让您的测试代码从
WinMain
运行,而您的生产代码从常规的旧main
运行。 当您使用“Windows”子系统构建时,您的测试将运行,而当您为Console
子系统构建时,您的生产代码将运行。 不过,我不知道链接器是否会从生产版本中删除未调用的测试函数。I think having most of the code that is tested be in a library is best, but not necessarily practical in all cases.
One solution is to have a separate project configuration (e.g., Debug, Release and Test) and have your test code in separate files which are marked as "Excluded From Build" under the Debug and Release configurations. You can either have the simple code to initiate the tests within an
#ifdef
or have a stub version of the test runner that's included in non-Test builds.Another option (though it's rather hack-ish) is to have your test code run from
WinMain
and your production code run from regular oldmain
. When you build using the "Windows" subsystem your tests will run, and when you build for theConsole
subsystem your production code will run. I don't know off-hand whether the linker will drop the un-called test functions from the production build, though.