Как улучшить покрытие веток в C++
У меня довольно большой набор тестов для библиотеки C++ с почти 100% охватом линий, но только 55,3% охватом ветвей. Просматривая результаты lcov
Похоже, что большинство пропущенных веток можно объяснить многими способами C++. std::bad_alloc
Например, всякий раз, когда std::string
построен
Я спрашивал себя, как улучшить охват филиалов в этой ситуации, и подумал, что было бы неплохо иметь new
оператор, который можно настроить, чтобы бросить std::bad_alloc
после стольких выделений, необходимых для попадания в каждую ветку, пропущенную в моем наборе тестов.
Я (наивно) пытался определить глобальный void* operator new (std::size_t)
функция, которая считает глобальный int allowed_allocs
и бросает std::bad_alloc
всякий раз, когда 0
достигнуто
Это имеет несколько проблем, хотя:
- Трудно получить количество
new
звонки до "первого" желаемогоthrow
, Я могу выполнить пробный прогон, чтобы рассчитать требуемые вызовы для успешного выполнения, но это не помогает, если несколько вызовов могут потерпеть неудачу в одной строке, например, что-то вродеstd::to_string(some_int) + std::to_string(another_int)
где каждыйstd::to_string
конкатенация черезoperator+
а также первоначальное распределение может быть неудачным. - Что еще хуже, мой набор тестов (я использую Catch) использует много
new
сам вызовы, так что даже если бы я знал, сколько вызовов требует мой код, трудно догадаться, сколько дополнительных вызовов из набора тестов необходимо. (Что еще хуже, у Catch есть несколько "подробных" режимов, которые создают много выходов, которые снова нуждаются в памяти...)
У вас есть идеи, как улучшить покрытие филиала?
Обновление 2017-10-07
Тем временем я нашел /questions/9074867/pokryitie-vetok-lcovgcov-s-proizvodstvom-vetok-c-povsyudu/9074881#9074881 со ссылкой на скрипт Python для фильтрации некоторых ветвей, созданных исключениями из вывода lcov. Это привело к тому, что охват моей ветки составил 71,5%, но оставшиеся небрежные ветки все еще очень странные. Например, у меня есть несколько операторов if, как это:
с четырьмя (?) ветвями, из которых одна осталасьreference_token
это std::string
).
У кого-нибудь есть идея, что означают эти ветви и как их можно ударить?
2 ответа
Я был успешным в этом некоторое время назад. У меня не было набора тестов, я просто запустил приложение, но обнаружил следующее.
Некоторая форма изоляции тестируемой вещи была важна. У меня были векторы и карты, которые в основном прерывали тестирование, когда они были также склонны.
Я думаю, что мне это удалось, когда у меня был IPC между инъекцией ошибки и точкой отказа. Это позволило вводить код неисправности инжектора и удалять независимо от тестируемого объекта.
Я также преуспел с подобными вещами, когда находился в одном и том же двоичном файле, но имел два независимых пути выделения - пользовательский распределитель для кода внедрения ошибки - который гарантирует, что в него не будут вмешиваться.
Моя успешная система взяла стек вызовов malloc и отправила его через IPC в другую программу. Он решил, видел ли он стек ранее, и если нет, то не удался. Затем программа может произойти сбой и произойдет сбой (дамп памяти был захвачен), после чего тестовая система будет перезапущена. Это значительно улучшило качество кода, который я разрабатывал.
Чей код вы хотите протестировать - ваш или Стандартная библиотека? Меня поражает, что в вашем отчете о покрытии говорится о ветвях в std::string, а не о вашем коде.
Можете ли вы настроить 'lcov', чтобы игнорировать библиотеку std и просто сосредоточиться на своем коде?