2010-06-28 3 views
1

Я использую Boost.Test для тестирования модулей и в настоящее время выполняю различные макетные серверы в отдельных потоках, которые запускаются из каждого теста. Чтобы более точно проверить мой код, макет-сервер должен действительно быть в отдельных процессах.Boost.Test and Forking

Я думал о делать что-то вдоль этих линий:

MY_TEST() 
if (fork() == 0) { 
    runMockServer(); // responds to test requests or times out, then returns 
    exit(0); 
} 
// Connect to MockServ and Run actual test here 
END_TEST() 

, но я боюсь, что это будет завинтить систему тестирования.

Безопасно ли это? Кто-нибудь сделал что-то подобное?

Я использую Boost 1.34.1 на Ubuntu 8.04, если это имеет значение.

ответ

3

Это не похоже на модульное тестирование того, чего вы хотите достичь. Хотя я не понимаю, почему это было бы небезопасно. У вас может быть состояние гонки, когда ваш модульный тест подключается к MockServ, если он еще не готов, но это легко разрешимо.

Я никогда не делал что-то подобное прямо, но я написал модульные тесты для библиотек, которые обрабатывают дочерние процессы fork/exec, и работает безупречно.

+0

Когда вы говорите, что вы «письменные модульные тесты для библиотек, которые fork/exec», я предполагаю, что вы имеете в виду в контексте Boost.Test? –

+0

правильный, используя Boost.Test. –

+0

Спасибо. Из любопытства, почему бы вам сказать, что это не похоже на юнит-тестирование? –

3

Я использовал библиотеку тестов Boost Unit Test в аналогичных обстоятельствах с положительными результатами. Я хотел иметь автоматические тесты, чтобы увидеть, работала ли библиотека при форкировании. Хотя это было еще ближе к системному тесту, в моем случае я все использую доступные инструменты, если они достигают того, чего вы хотите.

Одним из препятствий для преодоления является сигнализация ошибок из дочернего процесса без использования макросов boost assert. Если, например, BOOST_REQUIRE, это приведет к преждевременному прекращению теста, и любые последующие тесты будут выполняться как в родительском, так и в дочернем процессах. Я закончил использование кода выхода процесса, чтобы сообщить об ошибке ожидающему родительскому процессу. Однако не используйте exit(), так как boost имеет atexit() крючки, которые сигнализируют об ошибках в дочернем процессе, даже если их нет. Вместо этого используйте _exit().

Установки, которые я использовал для тестов, были примерно такими.

BOOST_AUTO_TEST_CASE(Foo) 
{ 
    int pid = fork(); 
    BOOST_REQUIRE(pid >= 0); 
    if(pid == 0) // child 
    { 
    // Don't use Boost assert macros here 
    // signal errors with exit code 

    // Don't use exit() since Boost test hooks 
    // and signal error in that case, use _exit instead. 
    int rv = something(); 
    _exit(rv); 
    }else{ // parent 
    // OK to use boost assert macros in parent 
    BOOST_REQUIRE_EQUAL(0,0); 
    // Lastly wait for the child to exit 
    int childRv; 
    wait(&childRv); 
    BOOST_CHECK_EQUAL(childRv, 0); 
    } 

}