c ++ - CoInitializeEx for en boost :: test :: unit\_test

Indlæg af Hanne Mølgaard Plasc

Problem



I dag besluttede jeg at vide, om testdrevet udvikling for C ++ på Windows-platformen (ved hjælp af Visual Studio 2010 Premium).


Jeg kigget rundt, før jeg satte mig op for at prøve enheds testrammer. Jeg skulle sige, at jeg valgte boostpro.com 's udgivelse (nuværende er 1,44 hvis jeg husker korrekt). Dette har en konstruktion af det statiske bibliotek, så jeg bruger ikke DLL'en i mine tests.


Boosts enhedstestdokumentation fortæller om at adskille din kode fra din test suite, hvilket forekommer rimeligt. Men så skal du håndtere problemet med at henvise til din kode fra dit nu separate test suite projekt.


Så jeg har et biblioteksprojekt, som jeg vil teste (men jeg er stadig ikke sikker på, hvordan jeg skriver test, der kan referere til et .exe-projekt ...)


Så jeg lavede et særskilt projekt i min løsning kaldet enhedsprøver. Jeg tilføjede følgende kode:


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


Jeg linker statisk til min 'crash' -biblioteksprojektudgang, så tilføjede jeg følgende post-build-event for at få en rapport efterbygget:


"$(TargetDir)$(TargetName).exe" --result\_code=no --report\_level=short


Postbygningsproduktionen ser sådan ud:


1>------ Build started: Project: UnitTests, Configuration: Debug Win32 ------
1>  UnitTests.cpp
1>  UnitTests.vcxproj -> F:ProjectsCrash	runkDebugUnitTests.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


Jeg forventede, at EncoderAvailable-testen skulle mislykkes, da jeg ikke har initialiseret en COM-lejlighed til tråden. Jeg antager, at jeg ikke kan bruge automatiske tests, og i stedet skal jeg erstatte auto-testene med test, som jeg manuelt definerer mig i en hovedfunktion, og gør mine CoInitializeEx () opkald i hovedfunktionen.


Jeg har læst her, at du kan definere adgangspunktet og registrere dine egne funktioner, så jeg gav dette en chance: [7]


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


Her er bygningen ouptut:


    1>------ Build started: Project: UnitTests, Configuration: Debug Win32 ------
1>  UnitTests.cpp
1>  UnitTests.vcxproj -> F:ProjectsCrash	runkDebugUnitTests.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 ==========


Denne testfejl fejler på den første test LameEncoderAvailable, som er følgende enkle funktion:


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


Kan nogen fortælle mig, hvor det rigtige sted at lave CoInitializeEx () -opkaldet - jeg tror ikke, jeg skal gøre det en gang pr. Test - det skal kun ske en gang pr. Tråd ...


Hvad angår test af exe-projekter, antager du, at du kunne angive en separat main.cpp (testmain.cpp eller noget) og udelukke din rigtige main.cpp fra bygningen for at få adgang til din kode. Hvis nogen ved en mere elegant løsning på den ene, vil jeg være ivrig efter at høre om det ...

Bedste reference


Brug en Global Fixture. Fixtures er en fantastisk måde at oprette initialisering/shutdown kode for hver test. En global løsning giver dig mulighed for at definere initialisering/nedlukningskode for hele din test suite. [8]

Andre referencer 1


Uprøvet, men ville en global variabel, der påberåber CoInitializeEx () i konstruktørhjælpen?

Andre referencer 2


Hvorfor ikke lave CoInitialize, CoUnitialize for hver test?



  Efterfølgende opkald til CoInitialize eller CoInitializeEx på samme tråd vil lykkes, så længe de ikke forsøger at ændre samtidighedsmodellen, men returnerer S\_FALSE.



REDIGERE:


Forudsat at testene faktisk udføres samtidigt. En måde at gøre det på er at have en thread\_specific container, der indeholder et RAII CoInitialize/CoUnitialize objekt.

Andre referencer 3


Du behøver IKKE at bruge init\_unit\_test\_suite, da denne funktion udføres før nogen af ​​testene kører.


Du vil bruge Global fixture. Ring CoInitializeEx (NULL, COINIT\_MULTITHREADED);
 i konstruktør og CoUnInitializeEx (); i destructor