Давайте начнем с минимального рабочего примера:
main.cpp:
#include <iostream>
#include <string>
int main() {
std::cout << "hello " + std::to_string(42);
return 0;
}
Я компилирую этот код, используя следующие флаги:
[g++/clang++] -std=c++11 -g -Og --coverage -Wall -o main main.cpp
лязг 4.0.1
gcc 4.8.5.
Я получаю только 50% покрытия кода, так как компилятор генерирует код исключения, который не выполняется, как объяснено в другом вопросе stackoverflow.
Проблема в том, что отключение исключений через -fno-exceptions
это не вариант для меня. Код, который я пишу для модульных тестов, использует исключения, поэтому отключение всех из них не вариант.
Для создания отчета я использую gcovr
, в случае clang ++ дополнительно llvm-cov gcov
преобразовать это. Но я не связан с этими инструментами, поэтому, если у вас есть другие инструменты, которые не показывают такое поведение, пожалуйста, предложите их!
По сути, мне нужен способ для компиляции / записи модульных тестов для этого кода и получения 100% ветвления / условного покрытия с включенными исключениями. Есть ли способ?
Ну, я полагаю, что вы намерены не тестировать этот маленький кусочек кода, а использовать концепцию в проекте …
Код, который вы ввели, выдает исключение — bad_alloc
выдается, когда у вас нет памяти для хранения строки, которая будет создана с std::to_string
, Чтобы быть на 100% безопасным, std::to_string
должен быть окружен try-catch
где вы могли бы обработать ваше исключение.
Чтобы построить модульный тест с 100% охватом кода, вам нужно заставить исключение произойти — в этом конкретном случае почти невозможно гарантировать, так как параметр является постоянным числом. Но в вашем проекте вам, вероятно, нужно выделить некоторые данные, размер которых является переменным — в этом случае вы можете выделить в своем коде методы, которые выделяют память, чтобы протестировать их по отдельности. Затем вы передаете этим методам в тестовой функции огромное количество, которое будет выделено для оценки того, что вы поместили в свой блок catch (и проверьте, правильно ли вы его обрабатываете).
Например, этот код должен выдавать исключение, вы можете использовать его, чтобы вдохновить себя при создании ваших тестов (источник):
// bad_alloc.cpp
// compile with: /EHsc
#include<new>
#include<iostream>
using namespace std;
int main() {
char* ptr;
try {
ptr = new char[(~unsigned int((int)0)/2) - 1];
delete[] ptr;
}
catch( bad_alloc &ba) {
cout << ba.what( ) << endl;
}
}
Однако, если вы не планируете обрабатывать все bad_alloc
исключений (или абсолютно всех исключений) в вашем коде, нет никакого способа получить 100% покрытие — так как оно не будет покрыто на 100% … Хотя в большинстве случаев истинное 100% покрытие не является необходимым.
Других решений пока нет …