CoInitializeEx用于boost :: test :: unit_test

有一天,我决定我需要了解Windows平台上的C ++的testing驱动开发(使用Visual Studio 2010 Premium)。

在研究boost的unit testing框架之前,我看了一下。 我应该说,我select了boostpro.com的发布(目前是1.44,如果我没有记错的话)。 这有一个静态库的构build,所以我不使用我的testing中的DLL。

Boost的unit testing文档讨论了如何从testing套件中分离代码,这似乎是合理的。 但是,你必须处理从你现在独立的testing套件项目中引用你的代码的问题。

所以我有一个库项目,我想testing(但我仍然不知道如何编写可以引用.exe项目的testing…)

所以我在我的解决scheme中创build了一个单独testing项目。 我添加了下面的代码:

#include "stdafx.h" #define BOOST_TEST_MODULE Crash #include <boost/test/unit_test.hpp> #include "LameEncoder.h" BOOST_AUTO_TEST_SUITE(CrashTestSuite) BOOST_AUTO_TEST_CASE(EncoderAvailable) { using namespace Crash::SystemDevices::Audio::Compressors::LameEncoder; HRESULT hr = S_OK; CComPtr <IBaseFilter> spEncoder; hr = spEncoder.CoCreateInstance( CLSID_LAMEDShowFilter ); if( spEncoder.p ) spEncoder.Release(); BOOST_CHECK_EQUAL( hr, S_OK ); } BOOST_AUTO_TEST_CASE(ProfilesGenerated) { using namespace Crash::SystemDevices::Audio::Compressors::LameEncoder; BOOST_CHECK_EQUAL ( EncoderProfiles.size(), 6 ); } BOOST_AUTO_TEST_SUITE_END() 

我静态链接到我的“崩溃”库项目输出,然后我添加了以下后生成事件来获取报告后构build:

 "$(TargetDir)\$(TargetName).exe" --result_code=no --report_level=short 

后构build输出如下所示:

 1>------ Build started: Project: UnitTests, Configuration: Debug Win32 ------ 1> UnitTests.cpp 1> UnitTests.vcxproj -> F:\Projects\Crash\trunk\Debug\UnitTests.exe 1> Running 2 test cases... 1> f:/projects/crash/trunk/unittests/unittests.cpp(19): error in "EncoderAvailable": check hr == ((HRESULT)0L) failed [-2147221008 != 0] 1> 1> Test suite "Crash" failed with: 1> 1 assertion out of 2 passed 1> 1 assertion out of 2 failed 1> 1 test case out of 2 passed 1> 1 test case out of 2 failed 

我期望EncoderAvailabletesting失败,因为我还没有初始化线程的COM公寓。 我假设我不能使用自动testing,而是我需要用testing来replace自动testing,我在主函数中手动定义自己,并在主函数中执行我的CoInitializeEx()调用。

我读过这里 ,你可以定义入口点并注册你自己的函数,所以我给了这个一个去:

 #include "stdafx.h" #include <boost/test/unit_test.hpp> using namespace boost::unit_test; #include "LameEncoderTests.h" test_suite* init_unit_test_suite( int argc, char* argv[] ) { CoInitializeEx(NULL, COINIT_MULTITHREADED); framework::master_test_suite(). add( BOOST_TEST_CASE( &LameEncoderAvailable ) ); framework::master_test_suite(). add( BOOST_TEST_CASE( &LameEncoderProfilesGenerated ) ); CoUninitialize(); return 0; } 

这是build立ouptut:

  1>------ Build started: Project: UnitTests, Configuration: Debug Win32 ------ 1> UnitTests.cpp 1> UnitTests.vcxproj -> F:\Projects\Crash\trunk\Debug\UnitTests.exe 1> Running 2 test cases... 1> f:/projects/crash/trunk/unittests/lameencodertests.h(17): error in "LameEncoderAvailable": check hr == ((HRESULT)0L) failed [-2147221008 != 0] 1> 1> Test suite "Master Test Suite" failed with: 1> 1 assertion out of 2 passed 1> 1 assertion out of 2 failed 1> 1 test case out of 2 passed 1> 1 test case out of 2 failed 1> ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== 

那个testing失败的第一个testingLameEncoderAvailable,这是下面的简单function:

 void LameEncoderAvailable() { using namespace Crash::SystemDevices::Audio::Compressors::LameEncoder; HRESULT hr = S_OK; CComPtr<IBaseFilter> spEncoder; hr = spEncoder.CoCreateInstance( CLSID_LAMEDShowFilter ); if( spEncoder.p ) spEncoder.Release(); BOOST_CHECK_EQUAL( hr, S_OK ); } 

任何人都可以告诉我在哪里做CoInitializeEx()调用的正确位置 – 我不认为我应该这样做一次每个testing – 它应该只做一次线程…

至于testingexe项目,我想你可以指定一个单独的main.cpp(testmain.cpp或其他),并从构build中排除你真正的main.cpp来访问你的代码。 如果有人知道这个更优雅的解决scheme,我会很想听到…

使用全球夹具 。 Fixtures是为每个测试设置初始化/关闭代码的好方法。 全局设备可以让你为整个测试套件定义初始化/关闭代码。

未经测试,但会在构造函数调用CoInitializeEx()的全局变量帮助吗?

为什么不为每个测试做CoInitialize,CoUnitialize?

在同一线程上对CoInitialize或CoInitializeEx的后续调用将成功,只要它们不尝试更改并发模型,但将返回S_FALSE。

编辑:

假设测试确实是同时执行的。 一种方法是拥有一个容纳RAII CoInitialize / CoUnitialize对象的thread_specific容器。

你不需要使用init_unit_test_suite,因为这个函数是在任何测试运行之前执行的。

你确实想使用全局夹具。 调用CoInitializeEx(NULL,COINIT_MULTITHREADED); 在构造函数和CoUnInitializeEx()中; 在析构函数中