На днях я решил, что мне нужно знать о тестовой разработке для C ++ на платформе Windows (с использованием Visual Studio 2010 Premium).
Я осмотрелся, прежде чем остановился на тестировании фреймворка для буст-тестов. Я должен сказать, что я выбрал релиз 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()
Я статически связываюсь с выводом проекта моей библиотеки "crash", затем я добавил следующее событие после сборки, чтобы получить отчет после сборки:
"$(TargetDir)\$(TargetName).exe" --result_code=no --report_level=short
Вывод после сборки выглядит следующим образом:
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 для потока. Я бы предположил, что я не могу использовать автоматические тесты, и вместо этого мне нужно заменить автоматические тесты на тесты, которые я сам определяю в основной функции и выполняю свои вызовы 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;
}
Вот выход сборки:
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 из сборки для доступа к вашему коду. Если кто-нибудь знает более изящное решение для этого, я был бы рад услышать об этом ...