Как программа тестирования должна сообщать об ошибках? Отображение сообщения об ошибке является очевидной возможностью:
if( something_bad_detected )
std::cout << "something bad has been detected" << std::endl;
Но это требует проверки результатов программы после каждого запуска, чтобы определить, произошла ли ошибка. Поскольку тестовые программы часто запускаются как часть набора тестов регрессии, проверка результатов для обнаружения сообщений об ошибках занимает много времени и ненадежна. Тестовые фреймворки, такие как GNU, могут выполнять проверки автоматически, но слишком сложны для простого тестирования.
Лучший простой способ сообщить об ошибках - вернуть программу тестирования. EXIT_SUCCESS
(обычно 0) при удовлетворительном выполнении тестовой программы и EXIT_FAILURE
при обнаружении ошибки. Это позволяет простому сценарию регрессионного теста автоматически и однозначно обнаруживать успех или неудачу. Дальнейшие соответствующие действия, такие как создание таблицы HTML или отправка оповещения по электронной почте, могут быть выполнены по сценарию и могут быть изменены по желанию без необходимости изменения реальных программ тестирования C++.
Протокол тестирования, основанный на политике возврата тестовых программ EXIT_SUCCESS
или EXIT_FAILURE
, не требует каких-либо вспомогательных инструментов; достаточно языка C++ и стандартной библиотеки. Программист должен помнить, однако, чтобы уловить все исключения и преобразовать их в выходы программы с ненулевыми кодами возврата. Программист также должен помнить, что не следует использовать для тестового кода стандартную библиотеку assert()
, поскольку в некоторых системах это приводит к нежелательным побочным эффектам, таким как сообщение, требующее ручного вмешательства.
Система тестирования Boost Test Library предназначена для автоматизации этих задач. Поставляемая библиотека main()
освобождает пользователей от беспорядочных обязанностей по обнаружению ошибок и отчетности. Пользователи могут использовать предоставленные инструменты тестирования для выполнения сложных задач проверки. Давайте посмотрим на следующую простую программу тестирования:
#include <my_class.hpp>
int main( int, char* [] )
{
my_class test_object( "qwerty" );
return test_object.is_valid() ? EXIT_SUCCESS : EXIT_FAILURE;
}
Есть несколько проблем с выше теста.
- Вы должны преобразовать
is_valid
в правильный код результата.
- Если исключение произойдет при построении метода test_object
is_valid
, программа рухнет.
- Вы не увидите никаких результатов, если вы запустите этот тест вручную.
Unit Test Framework решает все эти проблемы. Для интеграции с ним выше программа должна быть изменена на:
#include <my_class.hpp>
#define BOOST_TEST_MODULE
MyTest
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE
( my_test )
{
my_class test_object( "qwerty" );
BOOST_TEST( test_object.is_valid() );
}
Теперь вы получаете не только однородный код результата, даже в случае исключения, но и хорошо отформатированный вывод из инструмента BOOST_TEST
, если вы решите его увидеть. Есть ли другие способы проверки? В следующем примере тестовая программа показывает несколько различных способов обнаружения и сообщения об ошибке в функции add()
.
#define BOOST_TEST_MODULE
MyTest
#include <boost/test/unit_test.hpp>
int add( int i, int j ) { return i + j; }
BOOST_AUTO_TEST_CASE
(my_test)
{
BOOST_TEST
( add(2, 2) == 4 );
BOOST_TEST_REQUIRE
( add(2, 2) == 4 );
if (add(2, 2) != 4)
BOOST_ERROR
( "Ouch..." );
if (add(2, 2) != 4)
BOOST_FAIL
( "Ouch..." );
if (add(2, 2) != 4)
throw "Ouch...";
BOOST_TEST
( add(2, 2) == 4,
"2 plus 2 is not 4 but " << add(2, 2));
}

|
Этот подход использует инструмент BOOST_TEST , который отображает сообщение об ошибке (по умолчанию на std::cout ), которое включает в себя выражение, которое не удалось, а также значения на двух сторонах уравнения, имя исходного файла и номер строки исходного файла. Это также увеличивает количество ошибок. При завершении программы количество ошибок будет отображаться автоматически с помощью Unit Test Framework. |

|
Этот подход использует инструмент BOOST_TEST_REQUIRE , аналогичный подходу #1, за исключением того, что после отображения ошибки выбрасывается исключение, которое должно быть поймано Unit Test Framework. Этот подход подходит при написании явной программы тестирования, и ошибка будет настолько серьезной, что дальнейшее тестирование будет непрактичным. |

|
Этот подход аналогичен подходу No 1, за исключением того, что обнаружение ошибок и отчетность об ошибках кодируются отдельно. Это наиболее полезно, когда конкретное состояние требует нескольких независимых утверждений и/или не указывает на причину отказа. |

|
Этот подход аналогичен подходу No 2, за исключением того, что обнаружение ошибок и отчетность об ошибках кодируются отдельно. Это наиболее полезно, когда конкретное состояние требует нескольких независимых утверждений и/или не указывает на причину отказа. |

|
Этот подход приводит к исключению, которое будет поймано и описано в Unit Test Framework. Сообщение об ошибке, отображаемое при поимке исключения, будет наиболее значимым, если исключение получено из std:: Исключение или является char или std::string . |

|
Этот подход использует инструмент BOOST_TEST с дополнительным аргументом сообщения, аналогичный подходу #1, за исключением того, что аналогичный подход #3 отображает альтернативное сообщение об ошибке, указанное в качестве второго аргумента. |