CoInitializeEx用于boost :: test :: unit_test

时间:2011-03-07 12:57:08

标签: c++ windows visual-studio com boost-test

前几天,我决定在Windows平台(使用Visual Studio 2010 Premium)上了解C ++的测试驱动开发。

我在尝试使用boost的单元测试框架之前先看了一下。我应该说我选择了boostpro.com的发布(如果我没记错的话,当前是1.44)。这有一个静态库的构建,所以我不在我的测试中使用DLL。

Boost的单元测试文档讨论了从测试套件中分离代码,这似乎是合理的。但是,您必须处理从现在单独的测试套件项目中引用代码的问题。

所以我有一个我想测试的库项目(但是我仍然不确定如何编写可以引用.exe项目的测试...)

所以我在我的解决方案中创建了一个单独的项目,称为单元测试。我添加了以下代码:

#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()

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

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

post 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

我希望EncoderAvailable测试失败,因为我还没有初始化该线程的COM公寓。我假设我不能使用自动测试,而是我需要用测试替换自动测试我在主函数中手动定义自己,并在main函数中执行我的CoInitializeEx()调用。

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

#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;
}

这是构建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 ==========

第一个测试LameEncoderAvailable上的测试失败失败,这是以下简单的函数:

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()调用的正确位置 - 我认为每次测试都不应该这样做 - 每个线程应该只执行一次...

至于测试exe项目,我想你可以指定一个单独的main.cpp(testmain.cpp或其他东西)并从构建中排除你的真正的main.cpp来访问你的代码。如果有人知道一个更优雅的解决方案,我会热衷于听到它......

4 个答案:

答案 0 :(得分:2)

使用Global Fixture。夹具是为每个测试设置初始化/关闭代码的好方法。全局夹具允许您为整个测试套件定义初始化/关闭代码。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

为什么不为每项测试进行CoInitialize,CoUnitialize?

  

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

编辑:

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

答案 3 :(得分:0)

您不需要使用init_unit_test_suite,因为此函数在任何测试运行之前执行。

您确实想使用Global fixture。调用CoInitializeEx(NULL,COINIT_MULTITHREADED);  在构造函数和CoUnInitializeEx();在析构函数中