Визначення ступеня покриття коду на C
Визначення ступеня покриття коду на C/C++ тестами
Визначення ступеня покриття коду тестами - це дуже важливо як мінімум з двох причин. По-перше, за його допомогою ви перевіряєте, що тести виконують кожен із написаних вами рядків коду хоча б один раз. Якщо це не так, швидше за все, у вас досить фігові випробування. По-друге, ви можете знайти «мертвий» код, який насправді ніколи не виконується, та викинути його. Сьогодні ми з'ясуємо, як подивитися code coverage у програмах, написаних мовою C чи C++.
Якщо ви використовуєте GCC
Цей варіант був перевірений на FreeBSD 10.3 і GCC 4.9. Додатково нам знадобиться пакет lcov:
Під час складання проекту використовуємо такі прапори:
Збираємо проект, як завжди, потім виконуємо make check. Виконуватися він буде помітно повільніше, ніж зазвичай. При цьому буде згенеровано купу *.gcda файлів:
# у FreeBSD lcov інакше не знайде gcov sudo ln -s/usr/local/bin/gcov49/usr/local/bin/gcov
lcov --directory src --capture --output-file postgresql.info
Наприкінці виконання програми побачимо приблизно такий саморі:
Його можна, наприклад, ширяти регулярними виразами і в Jenkins вважати білд зламаним, якщо відсоток покриття коду тестами падає нижче заданого. Ми так намагалися робити, щоб програмісти не лінувалися писати тести на нові фічі. Перевірено, чи працює.
Так приблизно виглядає сам звіт:
За звітом видно, які шматки коду були виконані:
Все просто та зрозуміло!
Якщо ви використовуєте CLang
Під FreeBSD побудувати звіт про покриття коду за допомогою CLang 3.8 мені не вдалося. При компіляції вилітає помилка:
У результаті мені довелося скористатисяUbuntu 14.04 (я поки що не поспішаю переходити на 16.04). Для встановлення CLang та LLDB 3.8 говоримо:
У /etc/apt/sources.list дописуємо:
Проект збираємо з тими ж прапорами, що використовували у випадку з GCC:
Знову ж таки, говоримо make check . Дані про покриття коду збираються набагато швидше, ніж у випадку з GCC.
Тепер нам знадобиться приблизно такий скрипт /usr/bin/llvm-cov-wrapper:
use strict; use warnings;
my $args = "@ARGV" ; print STDERR "LLVM-COV-WRAPPER: args = '$args' \n" ;
if ( $args eq "-v" ) < print "gcov (FreeBSD Ports Collection) 4.2.4 20151202". "(prerelease) \n"; > else < my $cmd = "llvm-cov-3.8 gcov $args" ; print STDERR "LLVM-COV-WRAPPER: executing '$cmd' \n " ; system ($ cmd); >
Навіщо потрібен цей потворний хак з --gcov-tool? Справа в тому, що за умовчанням lcov використовує утиліту gcov. У системі встановлено gcov 4.8. Однак CLang генерує *.gcda , сумісні з версією 4.2 і тому gcov не може їх пропарсувати. Передаючи кастомний --gcov-tool ми (1) виводимо фальшивий номер версії, змушуючи lcov думати, що він використовує gcov 4.2 (2) замість gcov змушуємо lcov використовувати команду llvm-cov, яка чудово парсить згенеровані *.gcda файли.
Висновок
Зауважте, що у багатьох проектах з описаного вище робити потрібно далеко ще не все. Зокрема, у PostgreSQL можна отримати звіт про покриття коду тестами таким чином:
А чи будуєте ви звіти про покриття коду тестами і якщо так, то чим?