Вашему вниманию предлагается метод оптимизации функционального тестирования, основанный на анализе покрытия кода. На сегодняшний день существует большое количество приложений, которые могут собирать информацию о покрытии кода при тестировании. Предлагаемая методика показывает, как использовать эту аналитическую информацию с целью повышения эффективности тестирования
1 Один из методов оптимизации функционального тестирования
1.1 Введение
Вашему вниманию предлагается метод оптимизации функционального тестирования, основанный на анализе покрытия кода. На сегодняшний день существует большое количество приложений, которые могут собирать информацию о покрытии кода при тестировании. Собираемая информация содержится в метриках, которые показывают количество выполненных путей выполнения, строк кода, методов, классов, и т.п. при выполнении функциональных тестов. Предлагаемая методика показывает, как использовать эту аналитическую информацию с целью повышения эффективности тестирования
Использование анализа покрытия кода при функциональном тестировании помогает решить следующие задачи:
- Найти функциональность приложения, не оттестированную имеющимися тестами.
- Увеличить покрытие приложения тестами.
- Контролировать объем тестов, используя метрические значения анализа покрытия кода.
- Удалить тесты, которые не увеличивают покрытие кода.
- Сертифицировать программное обеспечение.
Кроме того, при недостаточной документированности требований к программному продукту, покрытие кода может помочь в нахождении функциональности, не покрытой тестами.
В этом докладе будет рассмотрено, как анализ покрытия кода может быть использован при организации тестирования программного обеспечения. Покрытие кода имеет свои сильные и слабые стороны и тестировщик должен будет выбрать правильный подход, используя различные методы измерений покрытия кода.
Анализ покрытия кода может помочь улучшить качество тестов, но это не обязательно означает улучшение качества конечного продукта. Покрытие кода тестированием это лишь одна из методик анализа качества тестирования и при тестировании программного обеспечения нельзя полагаться только на нее.
1.2 Тестирование "белого ящика" и функциональное тестирование
Анализ покрытия кода это одна из методик тестирования, так называемого, "белого ящика". Методика "белого ящика" позволяет тестировать программное обеспечение, сравнивая поведение с информацией, полученной при анализе исходного кода программы. Это контрастирует с функциональным тестированием (или "черного ящика"), при котором поведение приложения сравнивается с техническим заданием или спецификацией.
С первого взгляда, анализ покрытия кода не помогает в нахождении дефектов или проблем. Тем не менее, в случаях, когда спецификации не существует или она устарела к концу проекта, тестирование "белого ящика" является серьезным подспорьем для функционального тестирования.
1.3 Метрики анализа покрытия кода
1.3.1 Покрытие исполняемых блоков
Эта метрика позволяет понять, какая часть исполняемых блоков была вызвана при тестировании. Исполняемый блок - набор из нескольких операторов, выполняемый без перехода в другую часть приложения. Приложения оценки производительности обычно используют именно эту метрику. Недостаток этой метрики в том, что она невосприимчива ко многим операторам управления таким как if, ||, &&, switch,
1.3.2 Покрытие логики
Метрика показывает, какая часть условных операторов (например, If, while) была оттестирована для истинных и для ложных значений. Любое булево выражение считается, что будет либо истинно или ложно. Достоинство этой метрики в более полном покрытии всех условий в отличие от метрики исполняемых блоков. Недостаток в том что, метрика не покрывает всех вариантов выполнения булевых выражений в условных операторах.
1.3.3 Покрытие условий
Метрика покрытия условий показывает проверку каждого булевского подвыражения в булевском выражении, разделенного логическим И или логическим ИЛИ.
1.3.4 Покрытие условий и логики
Метрика покрытия условий и логики является составной из метрики покрытия условий и метрики покрытия логики. Достоинством этой метрики является ее простота при отсутствии недостатков входящих в нее метрик. Эта метрика очень подходит для C,C++, а также Java языков.
1.3.5 Покрытие множественных условий
Эта метрика показывает, какой процент всех возможных комбинаций булевских подвыражений в булевском выражении был протестирован. Для языков С, С++, Java, метрика покрытия множественных условий очень похожа на метрику покрытия условий.
1.3.6 Покрытие изменяемых условий и логики
Эта метрика требует тест кейсов, которые проверят каждое условие, которое может повлиять на принятие решения. Эта метрика была придумана в компании Боинг и покрытие кода этой метрикой необходимо для сертификации программного обеспечения в авиации (смотри параграф 1.8). Для С, С++ и Java эта метрика требует таких же тест кейсов, что и метрика покрытия условий и логики.
1.3.7 Покрытие путей выполнения (предикат)
Метрика покрытия путей выполнения показывает был ли при тестировании, пройден каждый возможный путь выполнения программы. Метрика путей выполнения также может называться как метрика покрытия предикат. Покрытие предикат представляет пути выполнения как возможные комбинации логических условий.
Чтобы собрать удовлетворительное покрытие по этой метрике нужно очень тщательное тестирование. Но основная проблема с этой метрикой это том, что количество путей растет экспоненциально к количеству условий в программе. Количество путей для выполнения десяти if операторов будет 1024.
1.4 Относительная "сила" метрик
Метрики можно сравнить по их "силе". Для более "сильных" метрик информация собирается с более низкого уровня. Более "сильные" метрики включают в себя более "слабые" метрики.
1. Метрика покрытия логики включает в себя метрику исполняемых блоков, так как покрытие каждого условия подразумевает покрытие каждого исполняемого блока. Это правило подходит только для случаев, когда выполнение логики не прерывается такими операторами как, например abort, exit в С/С++.
2. Метрика покрытие логики и условий включает в себя метрику покрытия условий и метрику покрытия логики - по определению.
3. Метрика покрытия путей выполнения или предикат, включает в себя метрику покрытия логики.
4. Метрика покрытие предикат включает в себя покрытие множественных условий, а так же большинство других метрик.
Нельзя сравнить метрики численно.
1.5 Цели покрытия кода при тестировании ПО
Для каждого проекта должен быть установлен минимальный процент покрытия как критерий выпуска приложения. Значение критерия должно основываться на доступных ресурсах и стоимости устранения ошибок после внедрения. Очевидно, что приложения с особыми требованиями к безопасности должны иметь более высокий критерий выпуска приложения. Другой вывод - это то, что более высокие требования покрытия кода должны быть для тестирования компонентов, чем для, например системного тестирования, поскольку более низкоуровневый код может исполняться для большого количества высокоуровневых вызовов.
Обычно, целями для метрик покрытия исполняемых блоков, покрытия логики, покрытия условий и логики могут быть 80-90% покрытия кода. Достижение покрытия 100% требует огромных усилий. Эти усилия лучше потратить на другие активности, например на формальное рецензирование документации. Но ставить цели на покрытие менее чем 80% кода не стоит.
1.6 Промежуточные цели покрытия кода при тестировании ПО
Промежуточные цели покрытия кода позволяют определить эффективную стратегию функционального тестирования, когда минимальными усилиями тестируется значительная часть приложения.
Очевидно, что наивысшая производительность достигается, когда большинство дефектов находится при наименьших усилиях. В тестировании, усилия учитываются на создание тест кейса, добавления в тестовый набор и на выполнение теста. Это означает, что анализ покрытия кода должен помочь в создании такой стратегии тестирования, когда покрытие кода должно увеличиваться как можно быстрее. Это увеличивает вероятность более быстрого нахождения проблем в приложении. На рисунке 1 и 2 показаны как должны расти производительность и эффективность при тестировании.
Рисунок 1
Рисунок 2
Одна из стратегий, которая обычно увеличивает покрытие - это сразу получить небольшое покрытие всего приложения, тестируя все основные функции, прежде чем тщательно тестировать одну функцию за другой. Например, в приложении, где создается большое количество отчетов, сначала стоит создать все виды отчетов и кратко их просмотреть, а не внимательно тестировать один за другим.
Вот пример стратегии функционального тестирования:
Цель 1: Вызвать не менее одной функции в 90% исходных файлов (самая слабая первоначальная цель)
Цель 2: Вызвать 90% функций (более сильная цель).
Цель 3: Достичь 90% покрытия логики и условий в каждой функции (более сильная цель).
Цель конечная: Достичь покрытия 90% путей выполнения приложения (самая сильная конечная цель).
Заметьте, что отсутствует цель достичь 100% покрытия для промежуточных целей. Это позволяет сосредоточить внимание на тестировании наиболее сложных частей функциональности и повысить эффективность тестирования.
Следует избегать использования "слабых" метрик для промежуточных целей вместе с "сильными" метриками для конечных целей. Использование "слабых" метрик может привести к тому, что будут неверно отобраны тест кейсы, выполнение которых можно отложить. "Сильные" же метрики потребуют более тщательного тестирования еще во время разработки, зато к концу проекта можно будет подойти с более высоким качеством и удовлетворить сильным конечным целям покрытия.
1.7 Почему невозможно достичь 100% покрытия
В принципе, достичь покрытия в 90% относительно легко. Но достичь покрытия уже в 95% будет не так просто. Например, придется загружать различные версии библиотек, где исправлены важные дефекты, которые не исправлены во всех библиотеках. В некоторых случаях необходимо будет сделать некоторые закрытые методы публичными, чтобы была возможность их вызвать. Такие решения могут оказаться слишком трудоемкими, но это поможет найти скрытые серьезные дефекты.
Кажется, что достижение 100% покрытия не имеет порой смысла. Иногда, практически невозможно вызвать некоторые линии кода, методы, или даже классы. Ниже приведены примеры проблем, когда сложно достичь 100% покрытия:
- Код, который выполняется только на специальных платформах. Например, код пользовательского интерфейса для Mac.
- Код для обработки ошибок.
- Методы внутри закрытых классов, которые обычно не выполняются, но должны быть разработаны для того, чтобы удовлетворять спецификации интерфейса.
- Код, который обрабатывает ошибки платформы, например проблемы с распознаванием кодирования UTF-8
Принимая во внимание эти проблемы, пытаться достичь 100% покрытия кода путем удаления кода, который не может быть протестирован, не является решением проблемы. Но это не значит, что не нужно пытаться достичь максимально возможного покрытия.
Очень часто помимо недоступного тестированию кода, приложение содержит код, который больше не нужен и может быть просто удален без проблем для работы приложения.
Код, который не может быть доступен через публичные интерфейсы, должен быть удален. Не доступный код не должен быть частью кода приложения.
1.8 Стандарт DO-178B для сертификации программного обеспечения
Примером промышленного стандарта качества, где удовлетворение стандартов покрытия кода является обязательным требованием, является DO-178B. Американское федеральное авиапромышленное агентство приняла стандарт DO-178B для сертификации авиационного программного обеспечения.
Требования DO-178B к покрытию кода приведены в таблице 1.
|
Параграф DO-178B |
Описание |
Уровень А Катастрофичный |
Уровень B Опасный |
Уровень С Значительный |
|
6.4.4.2 |
Достигнуто 100% покрытие множественных условий и покрытия логики |
Подтверждено независимой экспертизой |
Не нужно |
Не нужно |
|
6.4.4.2.a 6.4.4.2.b |
Достигнуто 100% покрытие логики |
Подтверждено независимой экспертизой |
Подтверждено независимой экспертизой |
Не нужно |
|
6.4.4.2.a 6.4.4.2.b |
Достигнуто 100% покрытие исполняемых блоков |
Подтверждено независимой экспертизой |
Подтверждено независимой экспертизой |
Удовлетворяет |
|
6.4.4.2.c 6.4.4.2.b |
Достигнуто связывание функциональных объектов по данным и управлению |
Подтверждено независимой экспертизой |
Подтверждено независимой экспертизой |
Удовлетворяет |
Таблица 1
Независимой экспертизой для анализа покрытия кода является анализ покрытия, проведенный специализированными программами.
1.9 Приложения анализа покрытия кода
Существует большое количество приложений, которые могут собирать метрики покрытия кода. В таблице 2 собраны данные по метрикам, собираемым некоторыми известными приложениями.
|
Приложение |
Блок |
Логика |
Условия |
Логика и условия |
Измененные условия/ Логика |
Путей Выполнения (предикат) |
Примечание |
|
Emma |
√ |
|
|
|
|
|
Свободное ПО Java |
|
Сobertura |
√ |
√ |
|
|
|
|
Свободное ПО Java |
|
Rational Pure Coverage |
√ |
√ |
√ |
√ |
|
|
Коммерческое ПО |
|
Clover |
√ |
√ |
|
|
|
|
Коммерческое ПО, Java, |
|
CodePro AnalytiX |
√ |
|
|
|
|
|
Коммерческое ПО, Java, Eclipse |
|
Testwell CTC++
|
√ |
√ |
√ |
√ |
√ |
|
Коммерческое ПО C++, C#, Java |
Таблица 2
Как показывает таблица 2, программы анализа кода, которые могут собрать "сильные" метрики являются обычно платными коммерческими решениями. К сожалению, на сегодняшний день программы свободно распространяемого ПО могут собрать только "слабые" метрики. Но даже такие метрики полезны для решения некоторых задач оптимизации функционального тестирования, таких как: поиск не выполненного (не оттестированного) кода, контроль объема созданных тестов, удаление тестов которые не увеличивают покрытия (насколько это возможно при использовании данных по "слабым" метрикам),
Выводы
Анализ покрытия кода даст больше результатов при тестировании приложений с большим количеством логики, чем при тестировании работы с данными.
Анализ покрытие кода является методикой "белого" ящика, которое может улучшить качество функционального тестирования. Наибольшая польза от него может быть при отсутствии спецификации.
Метрика покрытия логики и условий является наилучшей метрикой для анализа С, С++ и Java кода. Но для сертификации программного обеспечения необходимо делать анализ на основе более "сильных" метрик.
Покрытие в 100% подчас недостижимо и может потребовать очень больших усилий, которые лучше потратить на другие виды работ по обеспечению качества.
Постановка промежуточных целей может помочь повысить эффективность функционального тестирования. Не стоит ставить менее 80% покрытия для промежуточных целей.
Не все приложения, которые анализируют покрытие кода, могут предоставить анализ об "сильных" метриках. Решение о применении того или иного приложения должно основываться на целях которые должны быть достигнуты при тестировании.




