*** ВНИМАНИЕ: Блог переехал на другой адрес - demin.ws ***
Показаны сообщения с ярлыком gtest. Показать все сообщения
Показаны сообщения с ярлыком gtest. Показать все сообщения

понедельник, 18 апреля 2011 г.

Google Test 1.6.0

Только что вышла новая версия отличной библиотеки для unit-тестирования на С++ - Google C++ Testing Framework.

Вот список изменений:

  • New feature: ADD_FAILURE_AT() for reporting a test failure at the
    given source location -- useful for writing testing utilities.
  • New feature: the universal value printer is moved from Google Mock
    to Google Test.
  • New feature: type parameters and value parameters are reported in
    the XML report now.
  • A gtest_disable_pthreads CMake option.
  • Colored output works in GNU Screen sessions now.
  • Parameters of value-parameterized tests are now printed in the
    textual output.
  • Failures from ad hoc test assertions run before RUN_ALL_TESTS() are
    now correctly reported.
  • Arguments of ASSERT_XY and EXPECT_XY no longer need to support << to
    ostream.
  • More complete handling of exceptions.
  • GTEST_ASSERT_XY can be used instead of ASSERT_XY in case the latter
    name is already used by another library.
  • --gtest_catch_exceptions is now true by default, allowing a test
    program to continue after an exception is thrown.
  • Value-parameterized test fixtures can now derive from Test and
    WithParamInterface<T> separately, easing conversion of legacy tests.
  • Death test messages are clearly marked to make them more
    distinguishable from other messages.
  • Compatibility fixes for Android, Google Native Client, MinGW, HP UX,
    PowerPC, Lucid autotools, libCStd, Sun C++, Borland C++ Builder (Code Gear),
    IBM XL C++ (Visual Age C++), and C++0x.
  • Bug fixes and implementation clean-ups.
  • Potentially incompatible changes: disables the harmful 'make install'
    command in autotools.

Полная история версий.

Каких-то радикально новых возможностей вроде нет, но исправлено несколько неприятных багов.

Лично я очень ждал исправления мелких, но неприятных несовместимостей с компиляторами HP-UX, Sun и AIX.

Посты по теме и почти по теме:

UPDATE:

По ходу вышел еще и Google Mock 1.6.0.

Что нового тут:

  • Compilation is much faster and uses much less memory, especially
    when the constructor and destructor of a mock class are moved out of
    the class body.
  • New matchers: Pointwise(), Each().
  • New actions: ReturnPointee() and ReturnRefOfCopy().
  • CMake support.
  • Project files for Visual Studio 2010.
  • AllOf() and AnyOf() can handle up-to 10 arguments now.
  • Google Mock doctor understands Clang error messages now.
  • SetArgPointee<> now accepts string literals.
  • gmock_gen.py handles storage specifier macros and template return
    types now.
  • Compatibility fixes.
  • Bug fixes and implementation clean-ups.
  • Potentially incompatible changes: disables the harmful 'make install'
    command in autotools.

Полная история.

пятница, 16 апреля 2010 г.

Вышла новая версия Google Test 1.5.0

Сегодня вышла новая версия правильной библиотеки для unit-тестирования Google C++ Testing Framework 1.5.0.

Пока обзор будет краткий (фактически, это просто перевод официального анонса):
  • assert'ы теперь можно безопасно запускать из разных потоков (работает на платформах, где есть pthreads)
  • при использовании предикатов в EXPECT_TRUE() теперь можно самому задавать сообщения их ошибках
  • библиотеку теперь можно собрать как DLL (эту возможность многие ждали)
  • "упакованная" версия теперь входит состав дистрибутива, и ее не надо создавать самому через скрипт ("упакованная" версия - это просто два файла "gtest.h" и "gtest-all.cc", которые можно добавить в проект и не возиться с двоичной библиотекой)
  • система сборки теперь работает через CMake (это фантастически удобно)
  • добавлены две новые платформы: Solaris и AIX
  • убрана поддержка VC++ 7.1 с отключенными исключениями (если исключения включены, то все еще можно компилировать в VC++ 7.1)
Для тех, кто слышит про Google Test впервые, ниже предыдущие посты о Google Test и о тестировании в целом (многие на русском языке):

вторник, 13 октября 2009 г.

Google C++ Mocking Framework для начинающих

В рамках проекта популяризации культуры разработки софта с активным использованием тестирования выложил перевод Google C++ Mocking for Dummies на русский язык - Google C++ Mocking Framework для начинающих.

Использование Mock-объектов является очень интересной темой. И владение ей позволяет перевести unit-тестирование на принципиально иной уровень.

Как рассказано в статье, языки программирования типа Python или Java благодаря встроенному механизму Reflection позволяют строить Mock-объекты почти автоматически. С++ не дает такой роскоши, но гугловцы проделали отличную работу, создав Google Mock. Практически все, что можно как-то упростить или автоматизировать в плане mock-дел в С++, сделано и сделано добротно.

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

Посты по теме:

среда, 7 октября 2009 г.

Презентация от авторов Google C++ Testing Framework

В догонку к посту про новую версию Google Test, желающие могут заценить небольшую презентацию от ее авторов:



В презентации описывается не только сама библиотека, ее возможности и примеры использования, но и сам подход к разработке через тестирование (test driven development), рассмотрены несколько базовых советов по написанию удобного для тестирования кода и т.д.

В целом, не самые плохие десять минут, чтобы поглядеть и немного поразмыслить.

суббота, 3 октября 2009 г.

Google C++ Testing Framework 1.4.0

Вчера гугловцы анонсировали новую версию моей любимой библиотеки тестирования Google C++ Testing Framework - 1.4.0.

Что новенького?

Одна из главных новых возможностей - это "The event listener API". А попросту говоря, возможность полностью контролировать процесс печати результатов тестирования. Это позволяет формировать отчеты по тестированию в нужном формате без изменения кода библиотеки.

Например, стандартный вывод при выполнении элементарного теста (файл runner.cpp):
#include "gtest/gtest.h"

TEST(One, Simple) {
EXPECT_EQ(1, 2);
}

int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
будет таким:
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from One
[ RUN ] One.Simple
runner.cpp(4): error: Value of: 2
Expected: 1
[ FAILED ] One.Simple (15 ms)
[----------] 1 test from One (15 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (31 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] One.Simple

1 FAILED TEST
Для задания иного формата вывода нужно реализовать свой event listener (назовем его сервис печати). Например (файл runner.cpp):
#include "gtest/gtest.h"

using namespace ::testing;

// Данный класс заменит стандартный сервис печати.
class LaconicPrinter : public ::testing::EmptyTestEventListener {
// Вызывается до начала работы теста.
virtual void OnTestStart(const TestInfo& test_info) {
printf("*** Test %s.%s starting.\n",
test_info.test_case_name(), test_info.name());
}

// Вызывается при срабатывании какого-либо утверждения или явного вызова
// функции SUCCESS().
virtual void OnTestPartResult(const TestPartResult& test_part_result) {
printf("%s in %s:%d\n%s\n",
test_part_result.failed() ? "*** Failure" : "Success",
test_part_result.file_name(),
test_part_result.line_number(),
test_part_result.summary());
}

// Вызывается после выполнения теста.
virtual void OnTestEnd(const TestInfo& test_info) {
printf("*** Test %s.%s ending.\n",
test_info.test_case_name(), test_info.name());
}
};

TEST(One, Simple) {
EXPECT_EQ(1, 2);
}

int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);

// Получаем ссылку на список сервисов печати.
::testing::TestEventListeners& listeners =
::testing::UnitTest::GetInstance()->listeners();

// Удаляем стандартный сервис печати.
delete listeners.Release(listeners.default_result_printer());
// Добавляем наш сервис в список. Google Test самостоятельно удалит этот объект.
listeners.Append(new LaconicPrinter);

return RUN_ALL_TESTS();
}
Теперь отчет по работе тестов будет выглядеть так:
*** Test One.Simple starting.
*** Failure in runner.cpp:31
Value of: 2
Expected: 1
*** Test One.Simple ending.
Необходимо отметить, что одновременно может быть зарегистрировано несколько сервисов печати. Но в этом случае их выводы могут смешиваться и превращаться в кашу. Для избежания этого мы принудительно удаляем стандартный сервис печати, чтобы его вывод не мешал нашему.

Полностью интерфейс сервиса печати выглядит так:
class EmptyTestEventListener : public TestEventListener {
public:
// Вызывается при начале прогона всех тестов.
virtual void OnTestProgramStart(const UnitTest& unit_test);
// Вызывается при начале очередной итерации тестирования. Google Test
// позволяет управлять количеством итерации при прогоне тестов.
virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
// Вызывается до функции Environment::SetUp(), устанавливающей необходимое
// окружение для работы всех тестов.
virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
// Вызывается после функции Environment::SetUp(), устанавливающей необходимое
// окружение для работы всех тестов.
virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test);
// Вызывается при начале прогона группы тестов (у которых первый параметр
// макроса TEST/TEST_F одинаковый).
virtual void OnTestCaseStart(const TestCase& test_case);
// Вызывается при начале работы теста.
virtual void OnTestStart(const TestInfo& test_info);
// Вызывается при срабатывании утверждения в тесте или явного вызова
// функции SUCCESS().
virtual void OnTestPartResult(const TestPartResult& test_part_result);
// Вызывается после завершения работы теста.
virtual void OnTestEnd(const TestInfo& test_info);
// Вызывается после прогона группы тестов.
virtual void OnTestCaseEnd(const TestCase& test_case);
// Вызывается до функции Environment::TearDown(), производящей освобождение
// ресурсов, занятых Environment::StartUp().
virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
// Вызывается после функции Environment::TearDown().
virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test);
// Вызывается после очередной итерации тестирования.
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
// Вызывается после прогона всех тестов.
virtual void OnTestProgramEnd(const UnitTest& unit_test);
};
Также из значимого можно отметить новый ключ командной строки --gtest_shuffle, позволяющий запускать тесты в случайном порядке. Ключом --gtest_random_seed=SEED можно "управлять" случайностью этого порядка. Если SEED равен 0, то случайность будет действительно случайной, так как случайная последовательность будет определяться текущим временем.

Что приятно, теперь формат XML файлов, генерируемых при использовании ключа --gtest_output, полностью совместим с форматом JUnit. Это значит, что, например, система автоматической сборки, тестирования и интеграции Hudson теперь понимает отчеты Google Test без дополнительный конвертации.

Также теперь при работе в Visual Studio сообщения о сбойных тестах выводятся прямо в окно "Output", что позволяет, кликая на них, сразу находить строки, где сбоят тесты. Здорово, что данная фича основана на моем коде.

Еще, теперь время работы тестов печатается всегда, по умолчанию, то есть опция --gtest_print_time будто бы всегда включена.

Есть еще несколько незначительных улучшений:
  • поддержка CodeGear Studio
  • собственная реализация tuple для независимости от boost при использовании Combine()
  • множество улучшений для совместимости с Solaris, Windows Mobile и некоторыми другими платформами.
Радость, одно слово.

Я перестал что-то писать что-либо на C++ без тестов, а Google Test делает этот процесс простым и легким.

Я уже обновился до версии 1.4.0, а вы?

Ссылки по теме:

среда, 15 июля 2009 г.

Руководство для начинающих по Google Test

Выложил на Google Code свой перевод руководства для начинающих по Google Test.

Как всегда буду благодарен за замечания об ошибках, опечатках, и да вообще по стилистике в целом. Порой перевод технических терминов становится проблемой, так как с одной стороны для многих понятнее, когда используется просто английский термин (например, fixture), но с другой стороны хочется сделать жизнь как-то красивее и попытаться на своем родном писать без тотального засилия английских слов (их и так порядочно).

На отдельной странице будет общий список ресурсов о Google Test на русском языке. Очень пришелся кстати мой недавний пост о новшествах версии 1.3.0.

В планах перевод остальных документов.

В процессе работы над текстом перевода, у меня родилось вот такое небольшое лирическое отступление.

Я последнее время увлекся различными механизмами верстки при помощитекстовых языков разметки. И я не про HTML. Я говорю о таких вещах, как простые Wiki-диалекты, и заканчивая целым миром верстки под названием TeX. Периодически покуриваю на ночь документацию с http://www.ccas.ru/voron/latex.html. Начал я с совершенно дивного коротенького справочника, где сухо и сжато перечислены базовые элементы языка верстки LaTeX c примерами.

Например, моя любимая задача линейного программирования:



будет записываться так:
\[
\max_{n\in R}\sum_{j=1}^n
c_jx_j
;\;
\sum_{j=1}^n a_{ij}x_j\leqslant b_i, (i=1,\;2,\;\ldots,\;m)
\]
Если вы хотите в онлайне проиграться с набором формул в LaTeX, то рекомендую заглянуть сюда. Там, правда, не поддерживаются русские буквы в теле LaTeX команд, но для экспериментов это не проблема.

Когда я несколько лет назад верстал свою диссертацию в Ворде, я постоянно утыкался в корявости WYSIWYG подхода. Когда документ разрастается - сложная структура глав, много формул, картинок, внутренние и внешние ссылки, то уже крайне важной становится независимость содержания от, собственно, разметки. В WYSIWYG подходе на все случаи жизни уже не напасешься менюшек и кнопочек. Возникают корявости.

Безусловно, Ворд развивается семимильными шагами от версии к версии, оттачивая механизм стилей, без которого верстать что-то длинее десяти страниц вообще неудобно, но как же ему далеко от гибкости, которую придумали и реализовали в TeX десятки лет назад. К тому же чисто текстовое представление документа позволяет хранить его под контролем версий и удобно отслеживать изменения.

А объем и общая сложность документа моей диссертации была на порядки меньше любой технической книги даже среднего размера, особенно где много формул.

Вобщем, набивая перевод документации по Google Test, я просто отдыхал душой и попискивал от удовольствия, так как все происходило в Wiki-разметке в разделе документации проекта на Google Code.

Мечта - очень хотелось бы, чтобы когда-нидудь Blogspot реализовал бы альтернативный ввод постов с использованием Wiki-разметки, а не HTML. Хотя бы также, как это работает на Google Code. Ну а если еще и контроль версий будет, тогда вообще бесконечное счастье наступит.

Так если разобраться, единственная причина, почему нельзя вести блог прямо на Google Code в разделе Wiki - там нет трансляции постов в виде временной ленты. Если бы можно было в теле постов Блогспота на лету импортировать тест из документов Wiki c Google Code, то можно было бы удобно писать посты с применением Wiki-разметки и контролем версий, а отображать их в блоге.

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


Посты по теме:

четверг, 19 марта 2009 г.

Google Test Framework 1.3.0

Сегодня вышла новая версия Google Test Framework1.3.0.

Радостно, что авторы воплотили мою идею, когда вся библиотека собирается всего в два файла: gtest-all.cc и gtest.h. Теперь для этого есть специальный скрипт на Питоне. Распаковываем архив gtest-1.30.zip и запускаем:

python scripts\fuse_gtest_files.py . fuse
После этого во вновь созданном подкаталоге fuse будет находиться "упакованная" версия библиотеки в виде двух файлов gtest/gtest-all.cc и gtest/gtest.h. Моя аналогичная, но ручная сборка для предыдущей версии больше неактуальна.

Опять таки приятно, что включили мой микропатч для возможности установки флагов командной строки прямо в исходниках тестов. Это очень удобно. Например, есть возможность печати времени работы тестов. Но по умолчанию эта функция выключена, и для ее включения надо в командной строке сказать --gtest_print_time. Неудобно постоянно таскать за собой этот ключ. Теперь же можно прямо в тексте тестов, например, в головном модуле, задать этот параметр:

#include "gtest/gtest.h"
int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
testing::GTEST_FLAG(print_time) = true;
return RUN_ALL_TESTS();
}
Итак, новые возможности версии 1.3.0:
  • поддержка так называемых смертельных тестов для Windows (раньше это работало только под Linux)
  • параметр командной строки --gtest_also_run_disabled_tests для принудительного запуска отключенных тестов
  • возможность распараллеливать запуск тестов на разных машинах
Небольшая программа ниже демонстрируем новые "вкусности" Google Test.

Файл runner.cpp:
#include "gtest/gtest.h"

#include <fstream>
#include <iostream>
#include <cstdlib>

// -------------------------------------------------------

// Данная функция, если файл не существует, печатает сообщение
// об ошибке и завершает программу с ненулевым кодом.
void openfile(const char* name) {
std::ifstream is(name);
if (!is) {
std::cerr << "Unable to open the file" << std::endl;
std::exit(1);
}
}

// Тест для функции openfile().
TEST(OpenFileDeathTest, ExitIfNoFile) {
// Задаем заведомо несуществующий файл и смотрим - завершилась
// ли программа с ненулевым кодом. Также проверяем регулярным
// выражением то, что программа напечатала при выходе.
// Мы ожидаем слово "open" среди остального вывода.
ASSERT_DEATH({ openfile("__nofile__"); }, ".*open.*");
}

// -------------------------------------------------------

// Данная функция должна падать с assert'ом, если делитель
// равен нулю.
int divide(int a, int b) {
assert(b != 0);
return a / b;
}

// Тест для assert'а в функции divide().
TEST(AssertDeathTest, DivideByZero) {
// Задаем нулевой делитель и смотрим - упала или нет.
// Вывод программы при падении не проверяем.
ASSERT_DEATH({ divide(1, 0); }, "");
}

// -------------------------------------------------------

// Данная функция должна при ненулевом коде завершать
// программу, прибавив к заданному коду ошибки 50.
void abandon(int code) {
if (code != 0) std::exit(code + 50);
}

// Тест для функции abandon().
TEST(AbandonDeathTest, ExitCode) {
// Вызываем функцию и смотрим код возврата.
// Вывод программы при выходе не проверяем.
ASSERT_EXIT(abandon(200), testing::ExitedWithCode(250), "");
}

// -------------------------------------------------------

// Заведомо неработающий “сломанный” тест.
// Если имя группы тестов или теста в отдельности предварить
// словом DISABLED_, то тест не будет участвовать с запуске.
// Это удобно, когда какой-то тест сломан, времени на его
// отладку нет, но убирать его из тестирования совсем нельзя.
// В это случае его можно отключить. Google Test при каждом
// запуске будет напоминать, сколько имеется отключенных тестов.
// В процессе же работы над тестом можно запускать программу
// с параметром "--gtest_also_run_disabled_tests", который
// будет проверять также и отключенные тесты.
TEST(BadTest, DISABLED_Test) {
FAIL();
}

// -------------------------------------------------------

int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
// Принудительно печатаем время работы тестов.
testing::GTEST_FLAG(print_time) = true;
return RUN_ALL_TESTS();
}
Компилируем в Visual Studio:
cl /EHsc /I. /Ferunner_vs2008.exe /DWIN32 runner.cpp gtest\gtest-all.cc
Запускаем:
[==========] Running 3 tests from 3 test cases.
[----------] Global test environment set-up.
[----------] 1 test from OpenFileDeathTest
[ RUN ] OpenFileDeathTest.ExitIfNoFile
[ OK ] OpenFileDeathTest.ExitIfNoFile (31 ms)
[----------] 1 test from OpenFileDeathTest (31 ms total)

[----------] 1 test from AssertDeathTest
[ RUN ] AssertDeathTest.DivideByZero
[ OK ] AssertDeathTest.DivideByZero (31 ms)
[----------] 1 test from AssertDeathTest (31 ms total)

[----------] 1 test from AbandonDeathTest
[ RUN ] AbandonDeathTest.ExitCode
[ OK ] AbandonDeathTest.ExitCode (32 ms)
[----------] 1 test from AbandonDeathTest (32 ms total)

[----------] Global test environment tear-down
[==========] 3 tests from 3 test cases ran. (94 ms total)
[ PASSED ] 3 tests.

YOU HAVE 1 DISABLED TEST
Отлично, все работает. Также не забудем, что у нас таки есть один отключенный тест. Его можно запустить принудительно, использовав ключ --gtest_also_run_disabled_tests:
runner_vs2008.exe --gtest_also_run_disabled_tests
Получим следующее:
[==========] Running 4 tests from 4 test cases.
[----------] Global test environment set-up.
[----------] 1 test from OpenFileDeathTest
[ RUN ] OpenFileDeathTest.ExitIfNoFile
[ OK ] OpenFileDeathTest.ExitIfNoFile (31 ms)
[----------] 1 test from OpenFileDeathTest (31 ms total)

[----------] 1 test from AssertDeathTest
[ RUN ] AssertDeathTest.DivideByZero
[ OK ] AssertDeathTest.DivideByZero (32 ms)
[----------] 1 test from AssertDeathTest (32 ms total)

[----------] 1 test from AbandonDeathTest
[ RUN ] AbandonDeathTest.ExitCode
[ OK ] AbandonDeathTest.ExitCode (31 ms)
[----------] 1 test from AbandonDeathTest (31 ms total)

[----------] 1 test from BadTest
[ RUN ] BadTest.DISABLED_Test
runner.cpp(72): error: Failed
[ FAILED ] BadTest.DISABLED_Test (0 ms)
[----------] 1 test from BadTest (0 ms total)

[----------] Global test environment tear-down
[==========] 4 tests from 4 test cases ran. (94 ms total)
[ PASSED ] 3 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] BadTest.DISABLED_Test

1 FAILED TEST
Под занавес отмечу, что появился еще один новый ключ командной строки --help для печати на экран всех весьма многочисленных параметров Google Test.

Я уже обновился до версии 1.3.0, а вы?