Покрытие программного кода (структурное покрытие) — КиберПедия 

Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...

Наброски и зарисовки растений, плодов, цветов: Освоить конструктивное построение структуры дерева через зарисовки отдельных деревьев, группы деревьев...

Покрытие программного кода (структурное покрытие)

2020-12-06 878
Покрытие программного кода (структурное покрытие) 0.00 из 5.00 0 оценок
Заказать работу

Покрытие программного кода (структурное покрытие)

 

На этом семинаре познакомимся с одной из оценок качества системы тестов — с ее полнотой, т.е. величиной той части функциональности системы, которая проверяется тестовыми примерами.

Полная система тестов позволяет утверждать, что система реализует всю функциональность, указанную в требованиях, и, что еще более важно – не реализует никакой другой функциональности.

Степень покрытия программного кода тестами – важный количественный показатель, позволяющий оценить качество системы тестов, а в некоторых случаях – и качество тестируемой программной системы.

Одним из наиболее часто используемых методов определения полноты системы тестов является определение отношения количества тест-требований, для которых существуют тестовые примеры, к общему количеству тест-требований, — т.е. в данном случае речь идет о покрытии тестовыми примерами тест-требований.

В качестве единицы измерения степени покрытия здесь выступает процент тест-требований, для которых существуют тестовые примеры, называемый процентом покрытых тест-требований.

Покрытие требований позволяет оценить степень полноты системы тестов по отношению к функциональности системы, но не позволяет оценить полноту по отношению к ее программной реализации. Одна и та же функция может быть реализована при помощи совершенно различных алгоритмов, требующих разного подхода к организации тестирования.

 

Для более детальной оценки полноты системы тестов при тестировании стеклянного ящика анализируется покрытие программного кода, называемое также структурным покрытием.

 

Во время работы каждого тестового примера выполняется некоторый участок программного кода системы, при выполнении всей системы тестов выполняются все участки программного кода, которые задействует эта система тестов.

В случае, если существуют участки программного кода, не выполненные при выполнении системы тестов, система тестов потенциально неполна (т.е. не проверяет всю функциональность системы), либо система содержит участки защитного кода или неиспользуемый код (например, "закладки" или задел на будущее использование системы). Таким образом, отсутствие покрытия каких-либо участков кода является сигналом к переработке тестов или кода (а иногда – и требований).

 

К анализу покрытия программного кода можно приступать только после полного покрытия требований.

Полное покрытие программного кода не гарантирует того, что тесты проверяют все требования к системе. Одна из типичных ошибок начинающего тестировщика – начинать с покрытия кода, забывая про покрытие требований.

 

Замечание. Необходимо помнить, что разработка тестовых примеров, обеспечивающих полное покрытие тестируемого программного кода, относится к структурному тестированию кода. Перед началом структурного тестирования должно быть полностью закончено функциональное тестирование кода как черного ящика (чем мы и занимались на предыдущих семинарах).

Только после этого можно переходить к улучшению покрытия. В идеальном случае при полном покрытии функциональных требований должно получаться 100% покрытие кода.

Однако на практике такое происходит только в случае очень простого кода. Причина недопокрытия кода при полном покрытии требований – либо неполнота требований, либо недостаточно полный анализ требований тестировщиком. В первом случае обычно требуется доработка требований, во втором – тест-требований и тест-плана.

 

 

Уровни покрытия

1. По строкам программного кода (Statement Coverage) (метод покрытия операторов)

 

Для обеспечения полного покрытия программного кода на данном уровне необходимо, чтобы в результате выполнения тестов каждый оператор был выполнен хотя бы один раз.

Перед началом тестирования необходимо выделить переменные, от которых зависит выполнение различных ветвей условий и циклов в коде – управляющие входные переменные. Изменение значений этих переменных будет влиять на то, какие строки кода будут выполняться в различных тестовых примерах.

 

Если для тестирования задать значения переменных А=2, В=0, Х=3, будет реализован путь ace, т.е. каждый оператор программы выполнится один раз (рис. 1, а).

Но этот критерий на самом деле хуже, чем он кажется на первый взгляд.

Но, если внести в алгоритм ошибки – заменить в первом условии and на or, а во втором X > 1 на X < 1 (рис. 1, б), ни одна ошибка не будет обнаружена (см. табл. 1). Кроме того путь abd вообще не будет охвачен тестом и, если в нем есть ошибка, она также не будет обнаружена. В табл. 1 ожидаемый результат определяется по блок-схеме на рис. 1-а, а фактический по рис. 1-б.

Обратите внимание: ожидаемый результат определяется по алгоритму на рисунке 2.2, а фактический - по алгоритму рисунка 2.3, поскольку определяется чувствительность метода тестирования к ошибкам программирования. Как видно из этой таблицы, ни одна из этих ошибок не будет обнаружена.

Пример:

   Рис. 5.1. Пример алгоритма программы

а – правильный; б – с ошибкой

 

Как видно из этой таблицы, ни одна из внесенных в алгоритм ошибок не будет обнаружена.

Таблица 5.1. Результат тестирования методом покрытия операторов

Тест Ожидаемый результат Фактический результат Результат тестирования
A=2, B=0, X=3 X=2,5 X=2,5 неуспешно

 

Пример. В следующем фрагменте кода входными переменными являются prev и ShowMessage.

if (prev == "оператор" || prev == "унарный оператор")

{

if (ShowMessage)

{

   MessageBox.Show("Два подряд оператора на

      " + i.ToString() + " символе.");

}

else

{

     Log.Write("Два подряд оператора на " +

              + i.ToString() + " символе.")

}

Program.res = 4;

return "&Error 04 at " +

  + i.ToString();

}

 

Для того, чтобы полностью покрыть данный код по строкам, т.е. выполнить все строки кода, достаточно двух тестовых примеров:

                       1      2

prev               оператор оператор

ShowMessage   true     false

 

 

В первом тестовом примере осуществляется вход в первый условный оператор if, затем в первую ветвь второго оператора if.

Второй тестовый пример осуществляет аналогичные действия, но для второй ветви второго оператора if.

В результате все строки кода оказываются выполненными.

Легко увидеть, что, несмотря на полное покрытие по строкам, этот набор тестовых примеров не проверяет всей функциональности (даже не видя требований, логично предположить, что в них должно описываться поведение системы и для значения переменной prev = "оператор", и для значения prev = "унарный оператор").

Также проблемы этого метода покрытия можно увидеть и на примерах других управляющих структур. Например, проблемы возникают при проверке циклов do … while – при данном уровне покрытия достаточно выполнение цикла только один раз, при этом метод совершенно нечувствителен к логическим операторам || и &&.

Другой особенностью данного метода является зависимость уровня покрытия от структуры программного кода. На практике часто не требуется 100% покрытия программного кода, вместо этого устанавливается допустимый уровень покрытия, например 75%. Проблемы могут возникнуть при покрытии следующего фрагмента программного кода:

if (condition)

MethodA();

else

MethodB();

 

Если MethodA() содержит 99 операторов, а MethodB() — один оператор, то единственного тестового примера, устанавливающего condition в true, будет достаточно для достижения необходимого уровня покрытия.

При этом аналогичный тестовый пример, устанавливающий значение condition в false, даст слишком низкий уровень покрытия.

Покрытие программного кода (структурное покрытие)

 

На этом семинаре познакомимся с одной из оценок качества системы тестов — с ее полнотой, т.е. величиной той части функциональности системы, которая проверяется тестовыми примерами.

Полная система тестов позволяет утверждать, что система реализует всю функциональность, указанную в требованиях, и, что еще более важно – не реализует никакой другой функциональности.

Степень покрытия программного кода тестами – важный количественный показатель, позволяющий оценить качество системы тестов, а в некоторых случаях – и качество тестируемой программной системы.

Одним из наиболее часто используемых методов определения полноты системы тестов является определение отношения количества тест-требований, для которых существуют тестовые примеры, к общему количеству тест-требований, — т.е. в данном случае речь идет о покрытии тестовыми примерами тест-требований.

В качестве единицы измерения степени покрытия здесь выступает процент тест-требований, для которых существуют тестовые примеры, называемый процентом покрытых тест-требований.

Покрытие требований позволяет оценить степень полноты системы тестов по отношению к функциональности системы, но не позволяет оценить полноту по отношению к ее программной реализации. Одна и та же функция может быть реализована при помощи совершенно различных алгоритмов, требующих разного подхода к организации тестирования.

 

Для более детальной оценки полноты системы тестов при тестировании стеклянного ящика анализируется покрытие программного кода, называемое также структурным покрытием.

 

Во время работы каждого тестового примера выполняется некоторый участок программного кода системы, при выполнении всей системы тестов выполняются все участки программного кода, которые задействует эта система тестов.

В случае, если существуют участки программного кода, не выполненные при выполнении системы тестов, система тестов потенциально неполна (т.е. не проверяет всю функциональность системы), либо система содержит участки защитного кода или неиспользуемый код (например, "закладки" или задел на будущее использование системы). Таким образом, отсутствие покрытия каких-либо участков кода является сигналом к переработке тестов или кода (а иногда – и требований).

 

К анализу покрытия программного кода можно приступать только после полного покрытия требований.

Полное покрытие программного кода не гарантирует того, что тесты проверяют все требования к системе. Одна из типичных ошибок начинающего тестировщика – начинать с покрытия кода, забывая про покрытие требований.

 

Замечание. Необходимо помнить, что разработка тестовых примеров, обеспечивающих полное покрытие тестируемого программного кода, относится к структурному тестированию кода. Перед началом структурного тестирования должно быть полностью закончено функциональное тестирование кода как черного ящика (чем мы и занимались на предыдущих семинарах).

Только после этого можно переходить к улучшению покрытия. В идеальном случае при полном покрытии функциональных требований должно получаться 100% покрытие кода.

Однако на практике такое происходит только в случае очень простого кода. Причина недопокрытия кода при полном покрытии требований – либо неполнота требований, либо недостаточно полный анализ требований тестировщиком. В первом случае обычно требуется доработка требований, во втором – тест-требований и тест-плана.

 

 

Уровни покрытия

1. По строкам программного кода (Statement Coverage) (метод покрытия операторов)

 

Для обеспечения полного покрытия программного кода на данном уровне необходимо, чтобы в результате выполнения тестов каждый оператор был выполнен хотя бы один раз.

Перед началом тестирования необходимо выделить переменные, от которых зависит выполнение различных ветвей условий и циклов в коде – управляющие входные переменные. Изменение значений этих переменных будет влиять на то, какие строки кода будут выполняться в различных тестовых примерах.

 

Если для тестирования задать значения переменных А=2, В=0, Х=3, будет реализован путь ace, т.е. каждый оператор программы выполнится один раз (рис. 1, а).

Но этот критерий на самом деле хуже, чем он кажется на первый взгляд.

Но, если внести в алгоритм ошибки – заменить в первом условии and на or, а во втором X > 1 на X < 1 (рис. 1, б), ни одна ошибка не будет обнаружена (см. табл. 1). Кроме того путь abd вообще не будет охвачен тестом и, если в нем есть ошибка, она также не будет обнаружена. В табл. 1 ожидаемый результат определяется по блок-схеме на рис. 1-а, а фактический по рис. 1-б.

Обратите внимание: ожидаемый результат определяется по алгоритму на рисунке 2.2, а фактический - по алгоритму рисунка 2.3, поскольку определяется чувствительность метода тестирования к ошибкам программирования. Как видно из этой таблицы, ни одна из этих ошибок не будет обнаружена.

Пример:

   Рис. 5.1. Пример алгоритма программы

а – правильный; б – с ошибкой

 

Как видно из этой таблицы, ни одна из внесенных в алгоритм ошибок не будет обнаружена.

Таблица 5.1. Результат тестирования методом покрытия операторов

Тест Ожидаемый результат Фактический результат Результат тестирования
A=2, B=0, X=3 X=2,5 X=2,5 неуспешно

 

Пример. В следующем фрагменте кода входными переменными являются prev и ShowMessage.

if (prev == "оператор" || prev == "унарный оператор")

{

if (ShowMessage)

{

   MessageBox.Show("Два подряд оператора на

      " + i.ToString() + " символе.");

}

else

{

     Log.Write("Два подряд оператора на " +

              + i.ToString() + " символе.")

}

Program.res = 4;

return "&Error 04 at " +

  + i.ToString();

}

 

Для того, чтобы полностью покрыть данный код по строкам, т.е. выполнить все строки кода, достаточно двух тестовых примеров:

                       1      2

prev               оператор оператор

ShowMessage   true     false

 

 

В первом тестовом примере осуществляется вход в первый условный оператор if, затем в первую ветвь второго оператора if.

Второй тестовый пример осуществляет аналогичные действия, но для второй ветви второго оператора if.

В результате все строки кода оказываются выполненными.

Легко увидеть, что, несмотря на полное покрытие по строкам, этот набор тестовых примеров не проверяет всей функциональности (даже не видя требований, логично предположить, что в них должно описываться поведение системы и для значения переменной prev = "оператор", и для значения prev = "унарный оператор").

Также проблемы этого метода покрытия можно увидеть и на примерах других управляющих структур. Например, проблемы возникают при проверке циклов do … while – при данном уровне покрытия достаточно выполнение цикла только один раз, при этом метод совершенно нечувствителен к логическим операторам || и &&.

Другой особенностью данного метода является зависимость уровня покрытия от структуры программного кода. На практике часто не требуется 100% покрытия программного кода, вместо этого устанавливается допустимый уровень покрытия, например 75%. Проблемы могут возникнуть при покрытии следующего фрагмента программного кода:

if (condition)

MethodA();

else

MethodB();

 

Если MethodA() содержит 99 операторов, а MethodB() — один оператор, то единственного тестового примера, устанавливающего condition в true, будет достаточно для достижения необходимого уровня покрытия.

При этом аналогичный тестовый пример, устанавливающий значение condition в false, даст слишком низкий уровень покрытия.


Поделиться с друзьями:

Таксономические единицы (категории) растений: Каждая система классификации состоит из определённых соподчиненных друг другу...

Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...

Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни...

История развития пистолетов-пулеметов: Предпосылкой для возникновения пистолетов-пулеметов послужила давняя тенденция тяготения винтовок...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.051 с.