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 и т.д.
Ответы
Ответ 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
Обратите внимание, что это то, о чем я только что рассказывал, и, вероятно, есть много проблем с этим шаблоном, но это может послужить основой для некоторых лучших идей.
Ответ 4
Эта статья, которую я написал некоторое время назад, может представлять интерес http://petebarber.blogspot.co.uk/2012/04/unit-testing-when-success-case-is.html
Ответ 5
boost.type_traits, похоже, имеет то, что вы ищете.