Подтвердить что ты не робот

Unit test, что класс не копируется, а другие свойства времени компиляции

Есть ли способ протестировать ошибки во время компиляции, но без генерации ошибки? Например, если я создаю класс, который не копируется, я бы хотел проверить, что попытка его скопировать приведет к сбою компилятора, но я все равно хотел бы выполнить другие тесты времени выполнения.

struct Foo {
    int value_;
    Foo(int value) : value_(value) {}
  private:
    Foo(const Foo&);
    const Foo& operator=(const Foo&);
};

int main()
{
    Foo f(12);
    assert(f.value_ == 12);
    assert(IS_COMPILER_ERROR(Foo copy(f);));
} // Would like this to compile and run fine.

Я думаю, это не может быть сделано так просто, но есть ли идиоматический способ сделать это, или я должен использовать собственное решение (возможно, используя скрипты, компилирующие отдельные файлы тестов и тестирование результатов?)?

N.B.: Я взял не копируемый только для иллюстрации своей точки зрения, поэтому меня не интересуют ответы об использовании boost:: noncopyable и т.д.

4b9b3361

Ответ 1

Вы можете сделать это, используя make. Каждый тест будет фрагментом кода. Вот рабочий пример с двумя тестами для VС++. (Я использовал 2 командных файла для теста прохождения и теста отказа). Я использую GNU make здесь.

Makefile:


FAILTEST = .\failtest.bat
PASSTEST = .\passtest.bat

tests: must_fail_but_passes \
    must_pass_but_fails

must_fail_but_passes:
    @$(FAILTEST) [email protected]

must_pass_but_fails:
    @$(PASSTEST) [email protected]

must_pass_but_fails.cpp


struct Foo {
    int value_;
    Foo(void) : value_(0) {}
  private:
    Foo(const Foo&);
    const Foo& operator=(const Foo&);
};

int main() { Foo f(12); return 0; }

must_fail_but_passes.cpp


struct Foo {
    int value_;
    Foo(int value) : value_(value) {}
  private:
    Foo(const Foo&);
    const Foo& operator=(const Foo&);
};

int main() { Foo f(12); return 0; }

passtest.bat


@echo off
cl /nologo %1 >NUL
if %errorlevel% == 0 goto pass
@echo %1 FAILED
:pass

failtest.bat


@echo off
cl /nologo %1 >NUL
if not %errorlevel% == 0 goto pass
@echo %1 FAILED
:pass

Обратите внимание, что cl.exe(т.е. компилятор Visual Studio) должен быть на вашем пути для этого, чтобы "просто работать"

Удачи!

P.S. Я сомневаюсь, что это сделало бы меня знаменитым, хотя: -)

Ответ 2

BTW - единственная система сборки, которую я знаю, что позволяет такой тестовый готовый вариант - Boost.Build:

Отметьте здесь http://beta.boost.org/boost-build2/doc/html/bbv2/builtins/testing.html

Например,

# in your Jamfile
compile-fail crappy.cpp ;

.

int main()
{
  my crappy cpp file
}

Для получения дополнительных примеров просто grep -R compile-fail в вашем каталоге BOOST_TOP_DIR\libs.

Ответ 3

К сожалению, нет простого способа проверить ошибку компиляции так, как вы хотите, я также хотел сделать это раньше.

В любом случае, если ваши тесты достаточно малы, вы можете написать короткий несовместимый код, например ваш образец, и проверить с помощью script, если возникшие ошибки верны или нет (опять вы только что сказали).

Примером такого рода может быть скрипт настройки Unix, более чем в нескольких сценариях, которые я видел, они пытались скомпилировать небольшие образцы для проверки версии/способностей компилятора, чтобы правильно настроить makefile.

Итак, по крайней мере, вы можете знать, что вы не одиноки. Теперь, если вы написали успешную тестовую структуру для такого рода вещей, вы, вероятно, стали бы известными:)

Изменить: Возможно, вы также можете использовать #define, который пытается или не компилирует несовместимый код примерно так:

#ifdef _COMPILETEST
#define TRY_COMPILE(...) (__VA_ARG__)
#else
#define TRY_COMPILE(...)
#end

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

Ответ 5

boost.type_traits, похоже, имеет то, что вы ищете.