Для чего нужна Google C++ Testing Framework?
Существует множество причин использовать эту платформу. В этом разделе будут рассмотрены некоторые из них.
Некоторые категории тестов сталкиваются с проблемами памяти, проявляющимися только при определенных условиях. Среда тестирования от Google имеет отличную поддержку для обработки таких ситуаций. С помощью платформы от Google вы можете выполнять один и тот же тест тысячи раз. При первом обнаружении проблемы автоматически вызывается отладчик. Все это может быть проделано с помощью всего лишь двух опций командной строки: --gtest_repeat=1000 --gtest_break_on_failure
.
В отличие от множества других систем тестирования, платформа компании Google содержит встроенные правила, которые можно размещать в программном коде с отключенной (в целях повышения производительности) обработкой исключений. Таким образом, правила также могут безопасно использоваться в деструкторах.
Запустить тесты достаточно просто. Просто вызовите встроенный макрос RUN_ALL_TESTS
вместо того, чтобы отдельно создавать для выполнения теста новый или производный выполняемый класс. Это существенное отличие от таких платформ, как, например, CppUnit.
Вы можете легко создать отчет в формате XML (Extensible Markup Language) с помощью опции --gtest_output="xml:<имя файла>"
. Для вывода XML-отчета в таких системах, как CppUnit и CppTest, вам необходимо написать существенно больший объем кода.
Создание базового теста
Рассмотрим макет простой функции вычисления квадратного корня, показанный в листинге 1.
Листинг 1. Макет функции вычисления квадратного корня
double square-root (const double);
Для отрицательных чисел эта функция возвращает значение -1
. Здесь будет полезно выполнить тесты как для положительных, так и для отрицательных чисел, поэтому так и поступим. В листинге 2 показан контрольный пример.
Листинг 2. Модульный тест для функции вычисления квадратного корня
#include "gtest/gtest.h" TEST (SquareRootTest, PositiveNos) { EXPECT_EQ (18.0, square-root (324.0)); EXPECT_EQ (25.4, square-root (645.16)); EXPECT_EQ (50.3321, square-root (2533.310224)); } TEST (SquareRootTest, ZeroAndNegativeNos) { ASSERT_EQ (0.0, square-root (0.0)); ASSERT_EQ (-1, square-root (-22.0)); }
В листинге 2 создается иерархия тестов с именем SquareRootTest
, а затем к ней добавляются два модульных теста с именами
PositiveNos
и ZeroAndNegativeNos
. TEST
– это встроенный макрос, определенный в модуле gtest.h (доступен с загружаемым исходным кодом) и помогающий создать иерархию. EXPECT_EQ
и ASSERT_EQ
также являются макросами — в первом случае контрольного примера выполнение теста продолжается даже при возникновении ошибки, в то время как во втором случае в этой ситуации выполнение теста прекращается. Безусловно, если квадратный корень из 0 отнюдь не 0, то в любом случае, тестировать особо нечего. Вот почему в тесте ZeroAndNegativeNos
используется макрос ASSERT_EQ
, тогда как в тесте PositiveNos
используется макрос EXPECT_EQ
, показывающий, сколько было случаев, когда функция вычисления квадратного корня завершалась с ошибкой, но выполнение теста не прекращалось.
Запуск первого теста
Теперь, когда вы создали ваш первый базовый тест, пришло время запустить его. В листинге 3 приведен код основной программы, выполняющей тестирование.
Листинг 3. Запуск теста функции вычисления квадратного корня
#include "gtest/gtest.h" TEST(SquareRootTest, PositiveNos) { EXPECT_EQ (18.0, square-root (324.0)); EXPECT_EQ (25.4, square-root (645.16)); EXPECT_EQ (50.3321, square-root (2533.310224)); } TEST (SquareRootTest, ZeroAndNegativeNos) { ASSERT_EQ (0.0, square-root (0.0)); ASSERT_EQ (-1, square-root (-22.0)); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
Метод
::testing::InitGoogleTest
работает в соответствии со своим названием – он инициализирует платформу, и его необходимо вызвать перед функцией RUN_ALL_TESTS
. Функцию RUN_ALL_TESTS
необходимо вызвать всего один раз, так как множественные вызовы этой функции не поддерживаются, поскольку конфликтуют с некоторыми расширенными возможностями платформы. Обратите внимание на то, что функция RUN_ALL_TESTS
автоматически определяет и запускает все тесты, определенные с помощью макроса TEST
. По умолчанию результат выводится на устройство стандартного вывода. В листинге 4 показан результат выполнения теста.
Листинг 4. Вывод теста функции вычисления квадратного корня
Running main() from user_main.cpp [==========] Running 2 tests from 1 test case. [----------] Global test environment set-up. [----------] 2 tests from SquareRootTest [ RUN ] SquareRootTest.PositiveNos ..user_sqrt.cpp(6862): error: Value of: sqrt (2533.310224) Actual: 50.332 Expected: 50.3321 [ FAILED ] SquareRootTest.PositiveNos (9 ms) [ RUN ] SquareRootTest.ZeroAndNegativeNos [ OK ] SquareRootTest.ZeroAndNegativeNos (0 ms) [----------] 2 tests from SquareRootTest (0 ms total) [----------] Global test environment tear-down [==========] 2 tests from 1 test case ran.
0 ms total) [ PASSED ] 1 test. [ FAILED ] 1 test, listed below: [ FAILED ] SquareRootTest.PositiveNos 1 FAILED TEST
Дополнительные опции Google C++ Testing Framework
Из листинга 3 видно, что функция InitGoogleTest
принимает и загружает аргументы в тестовую инфраструктуру. В этом разделе рассматриваются некоторые полезные действия, которые вы можете проделывать с этими аргументами.
Вы можете выгрузить вывод в файл формата XML, указав в командной строке опцию --gtest_output="xml:report.xml"
. Конечно, вы можете заменить имя report.xml
любым другим на свое усмотрение.
Существуют определенные тесты, которые иногда завершаются с ошибкой, но в большинстве случаев выполняются успешно. Это присуще проблемам, связанным с ошибкой в памяти. В таких случаях возможность выявить ошибку будет выше, если тесты выполняются множество раз. Если вы укажете в командной строке опции --gtest_repeat=2 --gtest_break_on_failure
, то один и тот же тест будет выполнен дважды. Если тест завершается с ошибкой, автоматически вызывается отладчик.
Не все тесты бывает необходимо запускать каждый раз, особенно если вы вносите изменения в код только определенных модулей. Для этого система тестирования от Google предоставляет в ваше распоряжение опцию --gtest_filter=<маска>
. Маска представляет собой набор регулярных выражений, разделенных двоеточиями (:). Например, опция
--gtest_filter=*
запускает все тесты, а опция --gtest_filter=SquareRoot*
запускает только тесты группы SquareRootTest
. Если вы хотите запустить тесты группы SquareRootTest
только для положительных значений, используйте опцию --gtest_filter=SquareRootTest.*-SquareRootTest.Zero*
. Обратите внимание на то, что маска SquareRootTest.*
включает выполнение всех тестов группы SquareRootTest
, а маска -SquareRootTest.Zero*
исключает выполнение тестов, имена которых начинаются с Zero.
В листинге 5 приведен пример запуска группы тестов SquareRootTest
с использованием опций gtest_output
, gtest_repeat
и gtest_filter
.
Листинг 5. Запуск тестов SquareRootTest
с опциями gtest_output
, gtest_repeat
и gtest_filter
[arpan@tintin] ./test_executable --gtest_output="xml:report.xml" --gtest_repeat=2 -- gtest_filter=SquareRootTest.*-SquareRootTest.Zero* Repeating all tests (iteration 1) .
. Note: Google Test filter = SquareRootTest.*-SquareRootTest.Z* [==========] Running 1 test from 1 test case. [----------] Global test environment set-up. [----------] 1 test from SquareRootTest [ RUN ] SquareRootTest.PositiveNos ..user_sqrt.cpp (6854): error: Value of: sqrt (2533.310224) Actual: 50.332 Expected: 50.3321 [ FAILED ] SquareRootTest.PositiveNos (2 ms) [----------] 1 test from SquareRootTest (2 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test case ran. (20 ms total) [ PASSED ] 0 tests. [ FAILED ] 1 test, listed below: [ FAILED ] SquareRootTest.PositiveNos 1 FAILED TEST Repeating all tests (iteration 2) . . . Note: Google Test filter = SquareRootTest.*-SquareRootTest.Z* [==========] Running 1 test from 1 test case. [----------] Global test environment set-up. [----------] 1 test from SquareRootTest [ RUN ] SquareRootTest.PositiveNos ..user_sqrt.cpp (6854): error: Value of: sqrt (2533.310224) Actual: 50.332 Expected: 50.3321 [ FAILED ] SquareRootTest.PositiveNos (2 ms) [----------] 1 test from SquareRootTest (2 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test case ran. (20 ms total) [ PASSED ] 0 tests. [ FAILED ] 1 test, listed below: [ FAILED ] SquareRootTest.PositiveNos 1 FAILED TEST
Временное отключение тестов
Предположим, вы приостановили выполнение определенной части кода. Можно ли временно отключить тест? Да, просто добавьте префикс DISABLE_
к логическому имени теста или к имени отдельного его модуля, и он перестанет выполняться. В листинге 6 показано, что вам необходимо сделать для того, чтобы отключить выполнение теста
PositiveNos
, приведенного ранее в листинге 2.
Листинг 6. Временное отключение тестов
#include "gtest/gtest.h" TEST (DISABLE_SquareRootTest, PositiveNos) { EXPECT_EQ (18.0, square-root (324.0)); EXPECT_EQ (25.4, square-root (645.16)); EXPECT_EQ (50.3321, square-root (2533.310224)); } OR TEST (SquareRootTest, DISABLE_PositiveNos) { EXPECT_EQ (18.0, square-root (324.0)); EXPECT_EQ (25.4, square-root (645.16)); EXPECT_EQ (50.3321, square-root (2533.310224)); }
Обратите внимание на то, что по окончании выполнения тестов среда тестирования Google выводит предупреждение о том, что имеются отдельные отключенные тесты. Это показано в листинге 7.
Листинг 7. Предупреждение среды Google об отключенных тестах
1 FAILED TEST YOU HAVE 1 DISABLED TEST
Если вы хотите продолжить выполнение отключенных тестов, укажите в командной строке опцию -gtest_also_run_disabled_tests
. В листинге 8 показан результат работы программы, когда запускается тест
DISABLE_PositiveNos
.
Листинг 8. Google позволяет запускать отключенные тесты
[----------] 1 test from DISABLED_SquareRootTest [ RUN ] DISABLED_SquareRootTest.PositiveNos ..user_sqrt.cpp(6854): error: Value of: square-root (2533.310224) Actual: 50.332 Expected: 50.3321 [ FAILED ] DISABLED_SquareRootTest.PositiveNos (2 ms) [----------] 1 test from DISABLED_SquareRootTest (2 ms total) [ FAILED ] 1 tests, listed below: [ FAILED ] SquareRootTest. PositiveNos
Все о правилах
Платформа тестирования компании Google содержит в себе множество предопределенных правил. Существует два типа правил – правила, имена которых начинаются с ASSERT_
, и правила, имена которых начинаются с EXPECT_
. Правила ASSERT_*
прерывают выполнение программы при нарушении условия, тогда как в случае правил EXPECT_*
выполнение программы продолжается. В обоих случаях при нарушении условий система выводит имя файла, номер строки и сообщение, которое вы можете определить самостоятельно. Одними из несложных правил являются ASSERT_TRUE (условие)
и ASSERT_NE (значение1, значение2)
. Первое из них предполагает, что указанное условие всегда должно выполняться, а второе – что два значения не должны совпадать. Эти правила также работают с определенными пользователями типами данных, но при этом вы должны выполнить перегрузку соответствующего оператора сравнения (==, !=, <= и т. д.).
Сравнение чисел с плавающей запятой
Google предоставляет в ваше распоряжение макросы для сравнения чисел с плавающей запятой, представленные в листинге 9.
Листинг 9. Макросы для сравнения чисел с плавающей запятой
ASSERT_FLOAT_EQ (expected, actual) ASSERT_DOUBLE_EQ (expected, actual) ASSERT_NEAR (expected, actual, absolute_range) EXPECT_FLOAT_EQ (expected, actual) EXPECT_DOUBLE_EQ (expected, actual) EXPECT_NEAR (expected, actual, absolute_range)
Почему нужны отдельные макросы для сравнения чисел с плавающей запятой? Разве не будет работать правило ASSERT_EQ
? Ответ заключается в том, что ASSERT_EQ
и связанные с ним макросы могут работать, а могут и не работать, и поэтому лучше использовать макросы, специально предназначенные для сравнения чисел с плавающей запятой. Обычно различные центральные процессоры и рабочие окружения хранят числа с плавающей запятой по-разному, и простые сравнения ожидаемых и фактических значений не работают. Например, правило ASSERT_FLOAT_EQ (2.00001, 2.000011)
сработает – Google не возвращает ошибок, если значения совпадают с точностью до четырех десятичных знаков. Если вам необходима более высокая точность, используйте правило ASSERT_NEAR (2.00001, 2.000011, 0.0000001)
, и тогда вы получите ошибку, показанную в листинге 10.
Листинг 10. Сообщение об ошибке, выводимое правилом ASSERT_NEAR
Math.cc(68): error: The difference between 2.00001 and 2.000011 is 1e-006, which exceeds 0.0000001, where 2.00001 evaluates to 2.00001, 2.000011 evaluates to 2.00001, and 0.0000001 evaluates to 1e-007.
«Смертельные» тесты
В системе Google C++ Testing Framework имеется интересная категория правил (ASSERT_DEATH
, ASSERT_EXIT
и т. д.), называющихся «смертельными» правилами. Эти правила используются для проверки того, было ли какое-либо сообщение об ошибке получено в результате передачи на вход функции некорректных данных, или же работа этой функции была завершена в соответствии с заранее определенным кодом завершения. Например, возвращаясь к листингу 3, неплохо было бы получить сообщение об ошибке при выполнении функции square-root (-22.0)
и выйти из программы со статусом -1
вместо получения значения -1.0
. В листинге 11 для такого сценария используется правило ASSERT_EXIT
.
Листинг 11. Выполнение «смертельного» теста платформы Google
#include "gtest/gtest.h" double square-root (double num) { if (num < 0.0) { std::cerr << "Error: Negative Inputn"; exit(-1); } // Код для 0 и положительных чисел… } TEST (SquareRootTest, ZeroAndNegativeNos) { ASSERT_EQ (0.0, square-root (0.0)); ASSERT_EXIT (square-root (-22.0), ::testing::ExitedWithCode(-1), "Error: Negative Input"); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
Правило ASSERT_EXIT
проверяет, была ли функция завершена в соответствии с заданным кодом завершения (т. е. аргументом функций exit
или _exit
), и сравнивает заключенную в кавычки строку с тем, что выводит функция на стандартное устройство сообщений об ошибках. Обратите внимание на то, что сообщения об ошибках должны выводиться на устройство std::cerr
, а не на std::cout
. В листинге 12 представлены макеты для правил ASSERT_DEATH
и ASSERT_EXIT
.
Листинг 12. Макеты для «смертельных» правил
ASSERT_DEATH(оператор, ожидаемое_сообщение) ASSERT_EXIT(оператор, предикат, ожидаемое_сообщение)
Google предоставляет в ваше распоряжение встроенный предикат ::testing::ExitedWithCode(код_завершения)
. Результат этого предиката будет истинным только в том случае, если программа завершается с тем же кодом завершения, что и аргумент код_завершения
этого предиката. Правило ASSERT_DEATH
проще, чем правило ASSERT_EXIT
– оно просто сравнивает сообщение об ошибке, выводимое на стандартное устройство, с ожидаемым сообщением, заданным пользователем.
Понимание тестовых фикстур
Перед началом модульного тестирования, как правило, выполняется некоторая пользовательская инициализация. Например, если вы пытаетесь определить время выполнения теста и занимаемый им объем памяти, то вам необходимо написать для этого теста определенный код, позволяющий измерить эти значения. Здесь в дело вступают фикстуры, помогающие вам настраивать такие тестовые окружения. В листинге 13 показано, как выглядит класс тестовой фикстуры.
Листинг 13. Класс тестовой фикстуры
class myTestFixture1: public ::testing::test { public: myTestFixture1( ) { // код инициализации } void SetUp( ) { // код, который будет выполнен перед началом теста } void TearDown( ) { // код, который будет выполнен сразу по завершении теста // при необходимости здесь можно вызывать исключения } ~myTestFixture1( ) { // очистка всех ресурсов, вызов исключений не допускается } // сюда можно поместить необходимые вам пользовательские объекты данных };
Класс фикстуры является производным от класса ::testing::test
, объявленного в модуле gtest.h
. В листинге 14 приведен пример, в котором используется класс фикстуры. Обратите внимание на то, что в данном примере вместо макроса TEST
используется макрос TEST_F
.
Листинг 14. Пример использования фикстуры
TEST_F (myTestFixture1, UnitTest1) { . } TEST_F (myTestFixture1, UnitTest2) { . }
Ниже перечислены несколько условий, которые необходимо учитывать при использовании фикстур:
- Вы можете выполнить инициализацию или распределение ресурсов как с помощью конструктора, так и с помощью метода
SetUp
– выбор остается за вами. - Вы можете освобождать ресурсы с помощью метода
TearDown
или с помощью функции деструктора. Однако если вы хотите использовать обработку исключений, вы должны делать это только через методTearDown
, поскольку вызов исключения в деструкторе может привести к непредсказуемым результатам. - Макросы правил Google могут вызывать исключения на тех платформах, для которых они доступны в будущих версиях. Поэтому для лучшего сопровождения программ хорошо использовать макросы правил в коде метода
TearDown
. - Одни и те же фикстуры не используются в различных тестах. Для каждого нового модульного теста система создает новую тестовую фикстуру. Так что в листинге 14 метод
SetUp
(пожалуйста, используйте здесь правильную орфографию) вызывается дважды, потому что создаются два объектаmyFixture1
.
Заключение
В этой статье мы лишь поверхностно рассмотрели платформу Google C++ Testing Framework. Подробная документация по этой платформе доступна на сайте компании Google. Для профессиональных разработчиков я рекомендую ознакомиться с дополнительными материалами об открытых платформах регрессионного тестирования, таких как Boost unit test framework и CppUnit. Для получения дополнительной информации обратитесь к разделу Ресурсы.
Ресурсы для скачивания
- этот контент в PDF
www.ibm.com
Почему эксперимент в Google Analytics?
- бесплатный инструмент;
- все важные изменения во время теста будут приходить на почту;
- возможность протестировать одновременно до 35 страниц или их частей;
- выбор процент трафика, участвующего в эксперименте. Если имеете большое количество посетителей и не хотите задействовать все 100%, то выбираете в % соотношении аудиторию показа на период тестирования (1%, 5%, 10%, 25%, 50%, 75%, 100%);
- выбор цели эксперимента – длительность сеанса, отказы, просмотры страниц за сеанс, переход на страницу, события (клик по кнопке, по форме) или создать собственную (конверсии в «страница благодарности», в звонки и т.д.).
Не стоит запускать A/B тест в периоды «высоких» и «низких» сезонов, когда есть повышенный или пониженный спросы на Ваши товары или услуги.
Определив для себя цель эксперимента, приступаем к созданию эксперимента в Google Analytics.
convertmonster.ru
Как и любой уважающий себя язык программирования, C++ имеет фреймворки для написания модульных тестов, и даже не один, а очень много. В рамках этой заметки мы познакомимся с основами использования фреймворка Google Test. Это довольно легковесный, однако не в ущерб удобству и функциональности фреймворк, используемый в Chromium, LLVM, Protobuf, OpenCV, и других проектах. Кроме того, из IDE с ним умеет интегрироваться как минимум CLion.
Fun fact! Если вас интересует написание системных тестов, их намного удобнее писать на высокоуровневом языке вроде Python. В частности, для Python есть хороший тестовый фреймворк PyTest.
Все популярные дистрибутивы Linux имеют пакеты с Google Test. Например, в Ubuntu пакет называется libgtest-dev, а в Arch Linux — gtest.
Если вы используете CMake, то тесты, использующие Google Test, добавляются в проект очень просто:
В качестве примера напишем тесты на сериализацию и десериализацию объектов Date и User из статьи Работа с JSON на C++ при помощи библиотеки RapidJSON:
Заметьте, что, хотя здесь эта возможность и не используется, в общем случае Google Test позволяет заводить глобальное состояние, используемое разными тестами. Это может быть целесообразным, как минимум, для ускорения тестов. В остальном же приведенный код крайне прост, поэтому разбирать его более подробно я не вижу смысла.
Пример вывода программы:
Спрашивается, а зачем нужен этот фреймворк, если я могу написать обычную программу с assert’ами? Во-первых, такая программа завершит свое выполнение после первого упавшего теста, а Google Test всегда выполняет все тесты. Во-вторых, Google Test предлагает кучу готовых макросов для сравнения полученного результата с ожидаемым, например, ASSERT_FLOAT_EQ, ASSERT_DOUBLE_EQ, ASSERT_THROW, ASSERT_NO_THROW, и другие (см раз и два). Думаю, польза от перечисленных макросов понятна из их названий. В-третьих, когда тест падает, Google Test сам выведет вам ожидаемое и реально полученное значение:
Кроме того, Google Test позволяет запускать заданное подмножество тестов:
… а также запускать тесты многократно и в псевдослучайном порядке:
Если генерировать входные данные каждого теста псевдослучайным образом, получится что-то очень похожее на property-based тесты.
Наконец, Google Test умеет генерировать отчеты в формате XML, чтобы его было легче интегрировать с системами непрерывной интеграции (простите за тавтологию), интерактивными средами разработки, и так далее:
Резюмируя вышесказанное, Google Test делает всю рутину, позволяя вам сосредоточиться непосредственно на написании тестов. То есть, с ним вам придется писать намного меньше кода, чем без него.
Полную версию исходников к этому посту, как обычно, вы найдете на GitHub. Также вас может заинтересовать заметка Определение степени покрытия кода на C/C++ тестами, если вдруг вы ее пропустили.
А какими тестовыми фреймворками для C++ в это время суток пользуетесь вы?
Метки: C/C++, Тестирование.
eax.me
Как получить сертификат google analytics?
Входные данные по тесту:
- количество вопросов — 70;
- время прохождения — 90 минут;
- проходной бал — 80% ( минимум 56 вопросов).
Отличия от теста на английском языке:
- нет возможности поставить на паузу;
- нет возможности пропустить вопрос и возвратиться к нему через некоторое время;
- время прохождения теста 1.5 часа;
- возможность повторной сдачи через неделю;
- при не успешной сдаче следующая попытка доступна через неделю.
Самое сложное в этом тесте – верно понять, о чем именно вас спрашивают и правильно выбрать один или несколько вариантов ответа. Большинство вопросов относятся к особенностям работы с Google Analytics, основной темой в которых являются конкретные настройки GA для пользователей и фундаментальные аспекты функционирования системы.
Как подготовится к тесту по гугл аналитикс ?
При подготовке к тестированию у вас есть хорошая возможность систематизации ваших знаний про Google Analytics. Советую перед прохождением текста прочитать официальную справку и/или прослушать видеокурсы Google Analytics Academy, они помогут вам подготовиться к индивидуальной сертификации по Google Analytics. Для каждого курса в конце есть вопросы, которые можно проходить несколько раз.
И конечно полезно будет почитать официальный блог по GA.
Какие вопросы бывают в тесте по Google Analytics?
Основы:
- Знакомство с Google Analytics.
- Установка кода Google Analytics.
- Работа с данными в отчетах.
Настройка аккаунта:
- Управление аккаунтом.
- Отслеживание кампаний и интеграция с AdWords.
- Анализ AdWords.
- Куки и Google Analytics.
- Отслеживание электронной торговли.
- Домены и поддомены.
Настройка целей:
- Цели в Google Analytics.
- Фильтры в Google Analytics.
- Регулярные выражения и Google Analytics.
Понимание отчетов:
- Просмотры страниц, визиты и посетители.
- Временные метрики.
- Источники трафика.
- Отчеты по содержанию сайта.
Расширенное использование и анализ:
- Расширенная сегментация.
- Управление оповещениями.
- Внутренний поиск по сайту.
- Отслеживание событий и просмотров страниц.
- Дополнительные настройки.
semantica.in
Хороший код должен быть протестирован
Если код не протестирован, то он не хорош 🙂
Системы тестирования
При регулярном написании тестов разработчик сталкивается с рядом специфических проблем:
- Код теста содержит в себе много достаточно однотипных проверок. Необходимо максимально упростить и сократить время написания этого проверочного кода.
- Каждый тестируемый модуль / класс как правило требует проверки различных аспектов своего поведения. Необходимо максимально упростить процессы написания, организации и управления фрагментами кода.
- Для проведения тестов часто требуется создание специального тестового окружения: файлы с входными данными, сконструированные и приведённые в требуемое состояние объекты других классов / модулей, и т. п. После прогона теста и анализа результатов, тестовое окружение необходимо очистить либо вернуть в начальное состояние для прогона следующего теста.
Системы тестирования с той или иной успешностью решают эти и другие связанные с написанием тестов проблемы, избавляя программиста от написания кучи однотипного кода.
В рамках данного курса студентам предлагается использовать систему тестирования Google Testing Framework (далее, для краткости, GoogleTests)
Ключевые понятия
Кратко перечислим базовые строительные элементы GoogleTests.
- Assert | Утверждение — это выражение-проверка, результатом выполнения которого могут быть:
- Success | Успех — проверка выполнена успешно.
- Nonfatal Failure | Отказ — проверка не выполнена, но данный отказ не является критическим, выдается диагностическое сообщение, и выполнение теста продолжается.
- Fatal Failure | Критический отказ — проверка не выполнена, выдается диагностическое сообщение, и выполнение теста прерывается.
- Test | Тест — фрагмент программы с набором утверждений (проверок), которые проверяют состояние программы на разных этапах выполнения.
- Test Case | Набор тестов — тесты, объединенные разработчиком в некоторую логическую группу, например, все тесты, связанные с каким либо модулем / классом.
- Fixture | Фиксация — объект, связанный с тестовым набором, и выполняющий инициализацию / деинициализацию тестового окружения, для независимого выполнения каждого теста из набора.
Пройдемся по ним более подробно и с примерами.
Утверждения
Утверждения реализованы в виде макросов (макро-функций).
Утверждения, начинающиеся с префикса ASSERT_
, порождают в случае неуспеха критические отказы. Утверждения, начинающиеся с префикса EXPECT_
— некритические.
В случае критического отказа происходит немедленный возврат из функции, в которой проверялось это утверждение. Если за этим утверждением идет какой-то очищающий память код или какие-то другие завершающие процедуры, то можно получить утечку памяти / ресурсов.
Далее приводится синтаксис для критических утверждений, для некритических синтаксис аналогичен, различается только префикс в имени макро-функции (ASSERT_
/ EXPECT_
).
Простые логические проверки
ASSERT_TRUE(выражение);
— проверка выражения на истинностьASSERT_FALSE(выражение);
— проверка выражения на ложность
Проверка значений
Значения сравниваются с помощью операторов сравнения.
ASSERT_EQ(ожидаемое, реальное);
— проверка, что реальное значение точно равно ожидаемой величинеASSERT_NE(ожидаемое, реальное);
— проверка, что реальное значение не равно ожидаемой величинеASSERT_LT(ожидаемое, реальное);
— проверка, что ожидаемое значение < реальная величинаASSERT_LE(ожидаемое, реальное);
— проверка, что ожидаемое значение <= реальная величинаASSERT_GT(ожидаемое, реальное);
— проверка, что ожидаемое значение > реальная величинаASSERT_GE(ожидаемое, реальное);
— проверка, что ожидаемое значение >= реальная величина
Есть особый случай, который в GoogleTest обрабатывается не очевидным образом — это проверка указателя на равенство / не равенство NULL
. Обычное сравнение не вполне корректно работает, так как чаще всего указатель NULL
определён как целое число 0
, и его тип не совпадает с типом указателя.
Разработчики предлагают следующие обходные варианты решения:
Сравнение строк
ASSERT_STREQ(ожидаемая, реальная);
— проверка C-строк на равенствоASSERT_STRNE(ожидаемая, реальная);
— проверка C-строк на неравенствоASSERT_STRCASEEQ(ожидаемая, реальная);
— регистронезависимая проверка C-строк на равенствоASSERT_STRCASENE(ожидаемая, реальная);
— регистронезависимая проверка C-строк на неравенство
Сравнение чисел с плавающей запятой
ASSERT_FLOAT_EQ(ожидаемое, реальное);
— неточная проверка двух float значений на равенствоASSERT_DOUBLE_EQ(ожидаемое, реальное);
— неточная проверка двух double значений на равенствоASSERT_NEAR(ожидаемое, реальное, абсолютная_ошибка);
— неточная проверка двух значений с плавающей запятой на равенство с заданной величиной допустимой ошибки
Вызов отказа или успеха
SUCCEED();
— немедленное успешное завершение тестаFAIL();
— немедленное завершение теста с критическим отказомADD_FAILURE();
— вызвать некритический отказ и продолжить выполнение теста
В случае отказа, выдаётся диагностическое сообщение с данными, использованными в утверждении. Кроме того, можно задать собственный комментарий:
d:worktestmain.cpp(21): error: Value of: sin(3.14 / 2) Actual: 0.9999997 Expected: war_limit Which is: 4 war game is over
Тесты и наборы тестов
Для объявления и реализации теста используется макро-функция TEST()
. Этот макрос указывает набор, в который будет включён тест, и организует возвращающую void функцию, в которой можно использовать утверждения.
Макро-функция TEST()
принимает 2 параметра, уникально идентифицирующие тест, — название тестового набора и название теста. В рамках одного и того же тестового набора названия тестов не должны совпадать. Разработчики GoogleTest настоятельно советуют не использовать в названиях тестовых наборов символы подчёркивания, и этому правилу стоит следовать. Если название начинается с префикса DISABLED_
, это означает, что тест (набор тестов) помечен как временно не используемый.
Пример теста.
Как отмечалось ранее, критический отказ вызывает немедленный возврат из функции. Утверждения можно использовать не только в составе теста, но и вызывать из любой функции. Имеется лишь одно ограничение — утверждения, порождающие критические отказы не могут быть вызваны из функций возвращающих не void.
Фиксации и тестовое окружение
Фиксация представляет собой класс, унаследованный от ::testing::Test
, внутри которого объявлены все необходимые для тестирования объекты при этом в функции SetUp()
выполняется инициализация тестового окружения перед прогоном очередного теста, а в функции TearDown()
— обратная деинициализация после прогона этого теста.
Тесты, в которых используются фиксации, должны быть объявлены с помощью макро-функции TEST_F()
.
Эта макро-функция в использовании полностью аналогична TEST()
, только в качестве первого параметра ей передаётся не название набора тестов, а название фиксации.
С помощью фиксаций, например, можно тестировать код на утечки памяти.
Запуск тестов
Объявив все необходимые тесты, мы можем запустить их с помощью функции RUN_ALL_TESTS()
. Функцию можно вызывать только один раз. Желательно, чтобы тестовая программа возвращала результат работы функции RUN_ALL_TESTS()
, так как некоторые автоматические средства тестирования определяют результат выполнения тестовой программы по тому, что она возвращает.
Дополнение
Настройки для Qt
oop.afti.ru