#c #c 14 #catch-unit-test #catch2
#c #c 14 #catch-модульный тест #catch2
Вопрос:
У меня есть интеграционные тесты в моем проекте Catch2, которые зависят от настройки некоторого дорогостоящего глобального состояния. Я хотел бы инициализировать это глобальное состояние только тогда, когда тестировщик фактически будет тестировать системы, которые зависят от него.
То, что у меня есть, похоже, работает, но это немного ужасает… это зависит от довольно большого количества деталей реализации в конфигурации Catch.
Вот мой основной:
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
...
int main(int argc, const char* argv[])
{
// Construct a fake TestCaseInfo to match against the [integration] tag
const char * expensive_tag = "integration";
Catch::SourceLineInfo fake_source_line("?", 0)
Catch::TestCaseInfo fake_test_case("?", "?", "?", {expensive_tag}, fake_source_line);
Catch::Session session;
session.applyCommandLine(argc, argv);
auto test_spec = session.config().testSpec();
const bool want_integration_tests = test_spec.matches(fake_test_spec);
if(want_integration_tests)
{
do_expensive_setup();
}
return session.run();
}
И тогда мой тестовый файл просто:
#include "catch.hpp"
...
TEST_CASE("expensive-to-initialize system", "[.integration]")
{
REQUIRE(expensive_setup_is_done());
SECTION("has property 1") { ... }
SECTION("has property 2") { ... }
...
}
Обратите внимание, что, поскольку существует несколько разделов (и, в моем реальном проекте, несколько тестовых примеров), которые зависят от глобальной настройки, я не могу просто переместить инициализацию в начало TEST_CASE
.
Есть ли лучший способ?
Ответ №1:
Просто выполните инициализацию по требованию, используя что-то вроде std::call_once
:
TEST_CASE("expensive-to-initialize system", "[.integration]")
{
static std::once_flag init_flag;
std::call_once(init_flag, do_expensive_setup);
// ...
}
Это гарантирует, что do_expensive_setup
вызывается один раз, но только при необходимости. Если есть несколько мест, которым требуется эта настройка, просто оберните это в функцию.
Обратите внимание, что если do_expensive_setup
выдает ошибку, она может быть вызвана во второй раз. Но как только функция успешно завершится, это все.
Комментарии:
1. Ого, не знал об
std::call_once()
. Это идеально!2. будет ли static const bool dummy = do_expensive_setup(), false; также работать? Некоторым это может показаться более уродливым, но я не возражаю, поскольку я знаю о том, как работает статика.
3. @NoSenseEtAl Да, это тоже отлично работает (по модулю отсутствующих скобок).