В.В. Кулямин - Тестирование на основе моделей, страница 10
Описание файла
PDF-файл из архива "В.В. Кулямин - Тестирование на основе моделей", который расположен в категории "". Всё это находится в предмете "тестирование на основе моделей" из 9 семестр (1 семестр магистратуры), которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 10 страницы из PDF
В нашем случае концевая вершина ветвиD соответствует условному оператору, который выполнится и при покрытии другой ветви.Поэтому покрытие всех инструкций не гарантирует покрытия всех ветвей. Для полногопокрытия ветвей во втором примере можно использовать, например, тестовые данные 0, 1, 2и –2. Тест, использующий значение параметра 1, покажет, что для нечетных чиселсоответствующая пометка не выдается.Однако верно, что, если тесты дают 100% покрытия ветвей, они же всегда дадут и 100%покрытия инструкций. Для величин покрытия, меньших 100%, никаких общих соотношениймежду покрытием инструкций и ветвей указать нельзя. С одной стороны, количествоинструкций может значительно превышать количество ветвей, с другой стороны, половинаветвей программы может не содержать инструкций, как в приведенном примере. Поэтомупокрытие 95% инструкций может соответствовать только 5% покрытых ветвей и наоборот,покрыв 95% ветвей, можно покрыть только 5% инструкций.Но тот факт, что 100% покрытие ветвей автоматически означает 100% покрытияинструкций, уже достаточно важен.
Он показывает, что метрика покрытия ветвей «негрубее» метрики покрытия инструкций, выделяет не меньше разнообразных ситуаций. Если100% покрытия по одной метрике тестового покрытия влечет 100% покрытия по другойметрике, говорят, что первая метрика сильнее или тоньше. Соответственно, вторая слабееили грубее первой. Если одна метрика сильнее другой, а та тоже сильнее первой, ониэквивалентны. В этой ситуации все равно, какую из них использовать, если нас интересуеттолько полное, 100% покрытие.
Метрика покрытия ветвей сильнее метрики покрытияинструкций, а обратное не верно. Поэтому при достижении 100% покрытия ветвейтестирование в общем случае оказывается более полным, чем при покрытии 100%инструкций.Чтобы покрыть все ветви в коде, вычисляющем наибольший общий делитель, тоже нужнодополнить набор тестов, покрывающий все инструкции, например, взять тестовые данные<0, 1>, <1, 0>, <1, –2>, <1, 2>.
Чтобы убедиться в этом, достаточно изучить графа потокауправления этого кода, представленный ниже. В нем вершины, соответствующие операторамветвления и выхода из тела функции помечены номерами строк, содержащих эти операторы.В этом примере две ветви — отрицательные ветви для условных операторов в строках 7 и 12— тоже не содержат соответствующих инструкций.34567101223Допустим, однако, что мы, исправив последний пример, нечаянно внесли в него еще однуошибку. Теперь нечетные числа помечаются как надо, но условие пометки отрицательныхчисел неправильное.12345678910111213141516171819String classifier(int n){StringBuffer s = new StringBuffer();if(n == 0)return "ноль";if(n%2 == 0)s.append("четное ");elses.append("нечетное ");if(n < 0 && n%2 == 0)s.append("отрицательное");elses.append("положительное");return s.toString();}Набор тестовых данных 0, 1, 2, –2, по-прежнему покрывающий 100% ветвей, необнаруживает такую ошибку.
Чтобы выявить ее, необходимо использовать тесты,покрывающие комбинации условий, встречающихся в операторах ветвления.Комбинации условий определяется следующим образом. Выделим условия всехветвлений в коде программы, определяемых условными операторами, операторами циклаили операторами выбора.
Эти условия являются предикатами, составленными при помощилогических операций (отрицания «не», конъюнкции «и», дизъюнкции «или», равенства,неравенства или исключающего «или») из элементарных условий — логических формул,которые уже не разлагаются на составляющие логические формулы. Выделив всеэлементарные условия из ветвлений в коде заданной программы, мы можем составлятькомбинации из этих условий и их отрицаний, или, что то же самое, из их значений true и false(1 и 0). В приведенном примере элементарными условиями являются предикаты (n == 0),(n%2 == 0) и (n < 0). Из трех условий и их отрицаний можно составить 8 комбинаций, однаконе все эти комбинации будут выполнимы. Так, не может быть одновременно выполнено (n== 0) и (n < 0), или (n == 0) и !(n%2 == 0).
Выбросив все невыполнимые комбинации, мыполучим в данном примере только 5 комбинаций элементарных условий и их отрицаний —если (n == 0), значения остальных двух условий определяются однозначно, иначе дваоставшихся условия становятся независимыми и дают еще 4 комбинации.Номерn == 0n%2 == 0n<011102000300140105011Комбинация значений элементарных условий покрывается тестом, если во время еговыполнения эти условия в некоторый момент имеют в точности эти значения.Метрика покрытия комбинаций условий (multiple condition coverage) определяется какдоля покрытых текстами комбинаций значений элементарных условий, участвующих вусловиях ветвлений программы, по отношению к общему количеству выполнимыхкомбинаций значений элементарных условий.В приведенном выше примере набор тестовых данных 0, 1, 2, –2 не покрываеткомбинацию условий с номером 3 в таблице.
Покрыв эту ситуацию, например, с помощьюзначения параметра, равного –1, мы обнаружим внесенную в программу ошибку.Метрика покрытия комбинаций условий строго сильнее метрики покрытия ветвей,поскольку она сильнее, а при использовании составных предикатов в условиях ветвлений,как в нашем примере, становится неэквивалентной ей.В рассмотренном примере нам удалось достаточно быстро определить невыполнимыекомбинации, поскольку все условия зависят от одной целочисленной переменной n.
В общемслучае вопрос о выполнимости различных комбинаций достаточно непрост, посколькуэлементарные условия могут быть связаны неявно. Например, они могут использоватьглобальные переменные, значения которых подчиняются нетривиальным ограничениям,скажем, одна из переменных может представлять список каких-то объектов, а вторая —индекс одного из объектов в этом списке, либо –1, если список пуст. В общем случаеопределить выполнимость комбинации значений произвольных формул оказываетсядостаточно сложно, поскольку для этого нужно знать смысл используемых в условияхпеременных и функций.
Поэтому вычисление тестового покрытия по метрике покрытиякомбинаций условий в общем случае не автоматизируется.Другая трудность практического использования покрытия по этой метрике связана свозможным экспоненциальным ростом количества ситуаций, выделяемых для программыпри росте ее размера. Если в программе используется n операторов ветвления, условиекаждого из них элементарно и между этими условиями нет никаких связей, то возникаетвсего лишь 2n ветвей, но 2n возможных комбинаций условий.
Поэтому на практикеиспользуются метрики тестового покрытия, более сильные, чем покрытие ветвей, ноприводящие к меньшему числу различных ситуаций, чем покрытие комбинаций условий.Наиболее слабая из таких метрик — метрика покрытия условий и ветвей(condition/decision coverage или condition/branch coverage). Считается она следующимобразом. Для каждого элементарного условия определяется, сколько значений оно можетпринимать при всех возможных сценариях выполнения программы. Обычно, если нетспецифических ограничений, оно может принимать два значения. Но иногда встречаютсяпостоянные условия, которые либо всегда равны true, либо всегда равны false, при всехвыполнениях программы. Определяется общее число возможных значений элементарныхусловий, в которое каждое обычное условие вносит 2 значения, а постоянное условие — 1.Метрика покрытия условий и ветвей вычисляется как отношение общего количествазначений, которые все элементарные условия принимали в ходе теста, сложенного кколичеством выполненных ветвей к сумме общего возможного числу возможных значенийусловий и числа достижимых ветвей.Если при этом не учитывать покрытие ветвей, получится метрика покрытия условий(condition coverage), которая, однако, может оказаться не сильнее метрики покрытия ветвей— то, что все элементарные условия принимали все возможные значения, еще негарантирует, что все ветви были покрыты.При наличии n элементарных условий в программе метрика покрытия условий и ветвейопределяет не более 2n ситуаций.
Она, как легко видеть, сильнее метрики покрытия ветвей.Однако в нашем примере тесты, дающие 100% покрытия ветвей, дают и полное покрытиеусловий и ветвей, не обнаруживая внесенную ошибку.Более сильная метрика покрытия — метрика модифицированного покрытия условий иветвей (modified condition/decision coverage, MC/DC). Набор тестов считается достигающим100% покрытия по этой метрике, если•каждая достижимая ветвь покрывается этим набором;•каждое непостоянное элементарное условие принимает оба возможных значения привыполнении этого набора;•для каждого составного условия ветвления и каждого входящего в него элементарногоусловия, изменение значения которого способно изменить значение всего условия, естьдва теста, в которых все остальные входящие в это составное условие элементарныеусловия имеют одни и те же значения, а данное элементарное условие и составноеусловие в целом в этих тестах имеют различные значения.Проще говоря, в полном тесте по метрике MC/DC должно быть продемонстрировано, чтокаждое элементарное условие, способное влиять на результирующее значение включающегоего условия ветвления, действительно изменяет его значение независимо от остальныхэлементарных условий.В ошибочном коде, рассмотренном выше, значение условие третьего ветвления (n < 0)&& (n%2 == 0) может быть изменено за счет изменения значения любой из двух входящих внего формул.
Но сделать это можно, только изменяя значение формулы с true на false.Поэтому полный по MC/DC тестовый набор должен обеспечивать для этих формулвыполнение комбинаций значений <1, 1>, <0, 1>, <1, 0>. При этом внесенная ошибка будетобнаружена.Рассмотрим более сложный пример. Пусть в коде некоторой функции имеется дваусловия ветвлений: (x > 0) && (y > 0) || (x == 0) && (z != null) и (x < 0) && (z == null) || (z !=null) && z.isEmpty(). Составим таблицу возможных комбинаций значений элементарныхусловий и соответствующих значений условий ветвлений, учитывая, что выражениеz.isEmpty() определено, только когда выполнено z != null.x>0x == 0 x < 0 y > 0 z == null z != null z.isEmpty() III100100100020010011013001010014001101000500110110160011100170100010108010001111901001000100101010101101010111112010110001310000100014100001101151000100016100101010171001011111810011010В следующей таблице представлены только комбинации, существенные для первоговетвления.
Среди них найдем такие пары, что в них меняется значение только одногоэлементарного условия и всего условия в целом.x>0x == 0 y > 0 z == null Ix>0x == 0 y > 0z == null00000C0001000100AD00110B01001CG01010G01101DH01110H10000E10010F10101AE10111BFСоответствующие комбинации помечены в последних четырех столбцах таблицы. Двестроки помечены одной буквой, когда они входят в одну пару комбинаций. Эта букванаходится в столбце, соответствующем элементарному условию, которое меняет своезначение.