тестирование. Тестир. инф. систем Метод материалы. Сыркин Илья Сергеевич Тестирование информационных систем методические указания
![]()
|
5. Лабораторная работа №2. Использование инструментария анализа качества Целью работы является изучение инструментов анализа каче- ства ПО. Результатом работы является отчет, в котором должны быть приведены исходные коды программы, и результаты анализа качества разработанной программы. Для выполнения работы студент должен изучить приведенный ниже теоретический материал. Отчет сдается в распечатанном и электронном (файл Word) видах. В основе модели качества SonarQube лежит реализация мето- дологии SQALE (Software Quality Assessment based on Lifecycle Expectations) с определенными дополнениями. Как известно, мето- дология SQALE фокусируется в основном на сложности поддержки кода (maintainability) и не учитывает риски проекта. Например, если сегодня в проекте обнаружилась критическая проблема безопасно- сти, строгое следование методологии SQALE обязывает вас устра- нить все уже существующие проблемы с надежностью (reliability), возможностью изменений (changeability), тестируемостью (testability) и т. д., и только затем вернуться к новой критической проблеме. На самом деле, если потенциальные проблемы сущест- вуют в коде давно и не проявляют себя в виде пользовательских баг-репортов, гораздо важнее сфокусироваться на исправлении но- вых багов. С учетом этого, разработчики SonarQube модифицировали мо- дель качества, основанную на SQALE, чтобы акцентировать внима- ние на следующих важных моментах: Модель качества должна быть максимально простой в ис- пользовании. Баги и уязвимости не должны теряться среди проблем под- держиваемости (maintainability). Наличие серьезных багов и уязвимостей в проекте должно приводить к тому, что требования Quality Gate не выполнены. Проблемы поддерживаемости кода тоже важны, и их нельзя игнорировать. Вычисление стоимости устранения проблем (использование модели анализа SQALE) важно и должно выполняться. 29 Стандартный Quality Gate SonarQube использует следующие значения метрик для определения того, что код успешно прошел проверки: 0 новых багов. 0 новых уязвимостей. Коэффициент технического долга на новом коде <= 5%. Покрытие нового кода не ниже 80%. Команда Sonar определила семь смертных грехов разработчи- ков, увеличивающих технический долг: Баги и потенциальные багги. Нарушение стандартов кодирования. Дублирование кода. Недостаточное покрытие модульными тестами. Плохое распределение сложности. Спагетти-дизайн. Недостаточно или слишком много комментариев. Платформа SonarQube предназначена для того, чтобы помогать бороться с этими семью грехами. Рассмотрим более подробно основные возможности SonarQube. Главная страница На главной странице SonarQube вы видите список проектов, добавленных в систему, с краткой статистикой по каждому проекту: версия сборки, количество строк кода, количество багов, уязвимо- стей и признаков «кода с душком», дата последнего анализа: 30 Содержимое главной страницы можно настроить под ваши це- ли с помощью большого набора встроенных виджетов, позволяю- щих визуализировать состояние кода проектов в SonarQube. Метрики проекта Для получения более детальной информации о состоянии про- екта перейдем на страницу метрик проекта: 31 Здесь представлена информация о следующих метриках кода: Reliability (Надежность), Security (Безопасность), Maintainability (Поддерживаемость), Coverage (Покрытие тестами), Duplications (Дублирование), Size (Размер кодовой базы), Complexity (Циклома- тическая сложность), Documentation (Документирование кода) и Issues (Ошибки). Перейдя к метрике Reliability, мы получаем информацию об общем количестве обнаруженных багов и новые баги, обнаружен- ные во время последнего анализа, рейтинг надежности кода по шка- ле от A до E, где E – наихудший рейтинг, свидетельствующий о том, что был найден по крайней мере один blocker баг, а также вре- мя, необходимое на устранение всех найденных ошибок: 32 Платформа SonarQube позволяет анализировать метрики кода сверху вниз, от уровня проекта в целом до отдельных модулей и файлов. Так, например, если вы кликните на рейтинг надежности (Reliability Rating), вы увидите список файлов проекта, отсортиро- ванных по возрастанию рейтинга надежности. Это позволит сфоку- сироваться на наиболее проблемных участках кода: 33 Затем вы можете перейти к файлу с исходным кодом и к кон- кретным участкам кода, в которых обнаружены ошибки: 34 Такая навигация сверху вниз доступна и для других метрик. На странице метрики Security доступна информация об общем количестве уязвимостей, новых уязвимостях, рейтинге безопасно- сти (также по шкале от A до E), и времени, которое потребуется на устранение уязвимостей: Страница Maintainability содержит информацию о техническом долге в проекте: 35 Благодаря навигации «сверху вниз» вы можете перейти к спи- ску файлов, отсортированных по количеству обнаружений кода с душком: 36 и затем непосредственно к коду, который требует внимания: 37 На странице Coverage представлена информация о покрытии кода тестами: Страница Duplications содержит информацию о дублировании кода в проекте: 38 С помощью этой метрики вы легко можете обнаружить повто- ряющиеся строки, блоки кода и даже целые файлы: 39 Страница Size содержит информацию о размере проекта: ко- личество строк кода, выражений, функций, классов, файлов и ди- ректорий: На странице Complexity представлена информация о суммар- ной цикломатической сложности проекта, а также о средней слож- ности функций и файлов: 40 Страница Documentation предоставляет информацию о ком- ментариях в коде: отношение строк с комментариями к общему ко- личеству строк в проекте, количество строк с комментариями, ко- личество публичных API и уровень документирования публичных API: Последняя вкладка в разделе метрик проекта – Issues – содер- жит общее количество найденных проблем в коде (сумма количест- ва багов, уязвимостей и code smells), а также распределение про- блем по состоянию: открытые, переоткрытые, подтвержденные, ложные срабатывания и won't fix: 41 Навигация по ошибкам и коду После анализа метрик кода посмотрим, как SonarQube позво- ляет работать с найденными проблемами в коде. Для этого перей- дем в раздел Issues: Здесь представлены все найденные проблемы в коде с широ- кими возможностями фильтрации, что позволяет сфокусироваться на наиболее важных проблемах. Следует отметить, что SonarQube позволяет сохранять настройки фильтров, чтобы повторно их ис- пользовать. 42 По двойному клику на сообщении об ошибке вы можете пе- рейти к коду, в котором была найдена проблема. Также доступно детальное описание ошибки и рекомендации, как ее исправить: Обратите также внимание, что, благодаря интеграции с систе- мами контроля версий, видно, кто и когда внес изменения в код, вы- звавшие срабатывание анализатора: Интеграция с системами контроля версий позволяет также ав- томатически назначать баги в SonarQube на тех разработчиков, ко- торые их допустили. Также вы можете назначать баги на разработ- чиков вручную, изменять их тип (bug, vulnerability или code smell), важность, теги, добавлять комментарии. Для большего удобства ис- пользования доступна функция массового изменения багов: 43 Rules, Quality Profiles и Quality Gates Диагностические правила (Rules), профили качества (Quality Profiles) и границы качества (Quality Gates) – ключевые понятния платформы SonarQube. Каждый плагин для SonarQube, осуществ- ляющий статический анализ кода, содержит репозиторий с описа- нием диагностических правил, которые этот плагин выполняет. На- рушения этих правил используются для определения технического долга в коде и вычисления времени на устранение проблем. Для удобства использования правила объединяются в профили качества (Quality Profiles). По умолчанию, SonarQube создает дефолтный профиль качества для каждого поддерживаемого языка, но вы мо- жете создавать свои профили качества с тем набором диагностиче- ских правил, которые вам могут быть полезны. Например, для ана- лиза критически важных проектов, требования к качеству кода ко- торых самые строгие, можно определить профиль качества, содер- 44 жащий все доступные диагностики, а для менее критичных проек- тов можно определить менее строгий профиль качества, содержа- щий только серьезные ошибки, что позволит не отвлекаться на не- значительные code smells. Quality Gate – это индикатор соответствия (или несоответст- вия) кода проекта заданным пороговым значениям метрик. По умолчанию, все проекты, добавленные в SonarQube, используют стандартный quality gate, в котором определены следующие метри- ки и их пороговые значения: Новые баги = 0 Новые уязвимости = 0 Коэффициент технического долга на новом коде <= 5% Покрытие нового кода >= 80% Контрольные вопросы 1. Какие действия необходимо выполнить, чтобы определить метрики качества кода? 2. Каким образом определяется покрытие кода? 45 6. Лабораторная работа №3. Функциональное тестирование Целью работы является изучение функционального тестирова- ния ПО. Результатом работы является отчет, в котором должны быть приведены исходные коды программы, результаты функцио- нального тестирования ПО. Для выполнения работы студент должен изучить приведенный ниже теоретический материал. Отчет сдается в распечатанном и электронном (файл Word) видах. 6.1. Определение Функциональное тестирование – это проверка ПО на правиль- ность функционирования в идеальных условиях, в отличие от не- функционального, где либо условия неидеальны (нагрузочное тес- тирование), либо тестируется не правильность функционирования, а что-то иное (тестирование удобства пользования или структура программы). Есть много приложений, для которых производительность и удобство пользования некритичны. Во всяком случае, часто требо- вания к ПО содержат только функциональную часть. И практически не бывает требований к ПО без функциональной части. Отсюда де- лаем вывод, что функциональное тестирование проводить нужно для любого ПО. Как правило, функциональное и нефункциональное тестирова- ние ПО можно проводить параллельно, поэтому обычно это делает- ся разными людьми или командами. В большинстве источников указывается, что функциональное тестирование – это синоним black-box тестирования (при котором программа рассматривается как черный ящик). 6.2. Black-box, white-box, gray-box тестирование. По степени доступа к коду различают два типа тестирования: тестирование «черного ящика» (black-box), или функциональное тестирование – без доступа к коду, и «белого ящика» (white-box), или структурное тестирование – тестирование кода. В случае «черного ящика» программа рассматривается как ко- нечный автомат, с входными и выходными данными, набором внут- ренних состояний и переходов между ними. Тестируется правиль- ность поведения программы при различных входных данных и внутреннем состоянии. Правильность определяется исходя главным 46 образом из спецификации, а также любыми другими способами, кроме изучения кода (см. лекцию 1). В случае «белого ящика» тестировщик пишет тесткейсы, осно- вываясь исключительно на коде программы (тесты на правильность кода). Расширение black-box тестирования, в котором также приме- няется изучение кода, называется тестированием «серого ящика» (gray-box). В этом случае правильность поведения определяется любым удобным способом, в том числе изучением кода, что позво- ляет писать более эффективные black-box тесты (то есть тесты на правильность поведения). Терминология приведена по книге A Practitioner's guide to Software Test Design (Lee Copeland). 6.3. Методы отбора тестов для black-box тестирования Любая программа может рассматриваться как конечный авто- мат, с входными и выходными данными, набором внутренних со- стояний и переходов между ними. Чтобы провести полное тестирование программы, нужно про- верить правильность ее поведения при всех возможных комбинаци- ях входных данных и во всех возможных внутренних состояниях. Это невозможно из-за огромного числа комбинаций даже в про- стейших случаях. Поэтому на практике отбираются только наиболее важные тесты, такой отбор можно производить несколькими мето- дами. Тестирование сценариев использования – юз-кейсов (use-cases) Чтобы удостовериться в правильности перехода программы между различными внутренними состояниями, в идеале следует протестировать все возможные переходы между каждым из состоя- ний (не только одношаговые, но и многошаговые, то есть все пути в графе состояний). Чтобы уменьшить число тестов, можно проверить только те переходы, которые имеют смысл для пользователя. Use-case – это логически завершенная последовательность действий. Например, открытие файла в Notepad – это use-case, а выбор пункта меню «От- крыть файл» в Notepad – это не use-case, а лишь первый шаг юз- кейса «открытие файла». Тестирование сценариев является самым необходимым видом тестирования. Программа должна выполнять операции, для которых 47 она предназначена. Если пользователь может выбрать пункт меню, но файл не открывается – это очень серьезный баг. Здесь проверяется правильность перехода программы между внутренними состояниями при выполнении определенных операций (т. е. при определенных входных данных). Тестирование классов эквивалентности. Чтобы удостовериться в правильности поведения программы при различных входных данных, в идеале следует протестировать все возможные значения для каждого элемента этих данных (а так- же все возможные сочетания входных параметров). Например, пусть мы тестируем программу для отдела кадров, в ней есть поле «Возраст соискателя». Пример взят из книги A Practitioner's guide to Sofware Test De- sign (Lee Copeland). Требования по возрасту у нас будут такие: 0–13 лет – не нанимать; 14–17 лет – можно нанимать на неполный день; 18–54 года – можно нанимать на полный день; 55–99 лет – не нанимать. Чтобы проверить все возможные разрешенные данные (только разрешенные!) нам нужно протестировать ввод чисел от 0 до 99. (Возможен ведь еще ввод отрицательных чисел и нечисловых дан- ных.) Так ли необходимо тестировать все числа от 0 до 99? В слу- чае, если программа анализирует каждое чиcло по отдельности, вот таким образом, то видимо, да: if (age == 13) hireStatus=«NO»; if (age == 14) hireStatus=«PART»; if (age == 15) hireStatus=«PART»; if (age == 16) hireStatus=«PART»; if (age == 17) hireStatus=«PART»; if (age == 18) hireStatus=«FULL»; Но к счастью, программы обычно пишут по-другому: if (age >= 0 && age <=13) hireStatus=«NO»; if (age >= 14 && age <=17) hireStatus=«PART»; 48 if (age >= 18 && age <=54) hireStatus=«FULL»; if (age >= 55 && age <=99) hireStatus=«NO»; Становится очевидным, что можно протестировать одно из чи- сел каждого диапазона. Например: 5, 15, 20, 60. А также граничные значения (первое и последнее значения из каждого диапазона): 0, 13, 14, 17, 18, 54, 55, 99. Чтобы уменьшить количество тестируемых значений, произ- водится: а) разбиение множества всех значений входной переменной на подмножества (классы эквивалентности), а затем; б) тестирование одного любого значения из каждого класса. Все значения из каждого подмножества должны быть эквива- лентны для наших тестов. То есть, если тест проходит успешно для одного значения из класса эквивалентности, он должен проходить успешно для всех остальных. И наоборот, если тест не проходит для одного значения, он не должен проходить для всех остальных. В данном случае имеем 12 классов эквивалентности (каждое из 8 граничных значений по сути является отдельным классом). Чтобы проверить правильность работы программы на всех разрешенных данных, нужно провести 12 тестов. Запрещенные данные тестируются аналогично – можно выде- лить классы эквивалентности «дробное число от 0 до 99», «отрица- тельное число», «число больше 99», «набор букв», «пустая строка» и т. д. Таким образом, метод классов эквивалентности можно разде- лить на три этапа: 1. Тестирование разрешенных значений. 2. Тестирование граничных значений. 3. Тестирование запрещенных значений. Часто в литературе второй и третий этапы называют отдель- ными методами, но сути это не меняет. Попарное тестирование. Метод классов эквивалентности применяется для тестирования каждого входного параметра по отдельности. Пусть наша программа принимает на вход десяток параметров. Баги, возникающие при определенном сочетании всех десяти пара- 49 метров, довольно редки. Вообще, взаимное влияние параметров, о котором пользователь не знает – это баг интерфейса (интерфейс ин- туитивно не понятен). Чаще всего будут встречаться ситуации, в которых один пара- метр влияет на один из оставшихся, т. е. самыми частыми будут ба- ги, возникающие при определенном сочетании двух каких-то пара- метров. Таким образом, можно упростить себе задачу и протестиро- вать все возможные значения для каждой из пар параметров. Такой подход называется попарным тестированием (pairwise testing). Вот пример. Пусть имеется 3 двоичных входных параметра (3 чекбокса). Количество всех возможных комбинаций – 2 в степени 3 = 8 , значит, нужно произвести 8 тестов. Давайте попробуем сэко- номить, тестируя чекбоксы попарно. Выпишем все комбинации для первого и второго чекбоксов: 1-й 2-й 0 0 0 1 1 0 1 1 Добавим третий столбец так, чтобы во втором и третьем столбце получились все 4 двоичные комбинации. Это можно сде- лать разными способами, мы сделаем так (на первый столбец можно не обращать внимания): 1-й 2-й 3-й 0 0 0 0 1 0 1 0 1 1 1 1 Итак, с помощью четырех наборов входных данных (четырех тестов) мы протестируем две пары параметров: первый со вторым и второй с третьим. Осталось протестировать пару «первый с третьим». Выпишем отдельно 1 и 3 столбцы: 1-й 3-й 0 0 0 0 1 1 1 1 50 Как видно, мы имеем здесь две из четырех возможных комби- наций. Комбинации «01» и «10» здесь отсутствуют, а комбинации «00» и «11» присутствуют два раза. Ну что же, добавим еще 2 стро- ки (еще два теста) 1-й 3-й 0 0 0 0 1 1 1 1 0 1 1 0 Вернем второй столбец на его законное место: 1-й 2-й 3-й 0 0 0 0 1 0 1 0 1 1 1 1 0 1 1 0 Выходит, что последние два теста можно проходить при лю- бых значениях второго параметра. Можно дописать для определен- ности нули в эти пустые места: 1-й 2-й 3-й 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 0 0 Получаем 6 тестов вместо 8 при полном переборе. Можно ли сэкономить еще? Оказывается, можно. Вернемся к 1 шагу: 1-й 2-й 0 0 0 1 1 0 1 1 51 Давайте допишем третий столбец другим способом, поменяв порядок комбинаций: 1-й 2-й 3-й 0 0 1 0 1 0 1 0 0 1 1 1 Все комбинации для 1 и 2, а также для 2 и 3 параметра здесь есть. Отлично. Посмотрим теперь на комбинации 1 и 3 параметра 1-й 3-й 0 1 0 0 1 0 1 1 Ого! Что мы видим? Изменив порядок значений в третьем столбце, мы одним махом убили двух зайцев: скомбинировали и 2-й с 3-м, и 1-й с 3-м параметры. Итого имеем всего 4 строки, то есть 4 теста, эквивалентные первоначальным шести: 1-й 2-й 3-й 0 0 1 0 1 0 1 0 0 1 1 1 Полный перебор всех комбинаций в третьем столбце гаранти- рованно даст минимальное количество тестов. Однако, судя по то- му, что алгоритмы такой минимизации разрабатываются до сих пор, полный перебор неприемлем из-за большого времени исполнения. Существуют программы, дающие приемлемый результат в прием- лемое время, например, программа PICT от Microsoft. Ортогональный массив OA(N,k,s,t) – это двумерный массив из N рядов (итераций) и k колонок (факторов) из набора S (т. е. факто- ры могут принимать любое из s значений), обладающий свойством: выбрав любые t колонок (0<=t<=k) мы получим в рядах все комби- нации сочетаний из s по t (Количество повторений одинаковых комбинаций обозначают через λ. Чаще всего рассматривают масси- 52 вы, где λ = 1, т. е. каждая комбинация встречается только один раз). Параметр t называют мощностью ортогонального массива. В попарном тестировании применяется ортогональный массив мощности 2 – это двумерный массив такой, что любые 2 колонки этого массива содержат все возможные комбинации (пары) значе- ний, хранящихся в массиве. Использование информации о программе при gray-box тести- ровании. Главным минусом black-box тестирования является то, что тес- тировщик не знает, какую часть ПО он тестирует. Некоторые суще- ствующие пути в программе (о которых нет информации ни в тре- бованиях, ни в документации), могут никогда не быть проверены. Уменьшить количество таких путей можно путем анализа внутрен- него устройства программы. Информация о базе данных Если программа использует для своей работы какую-либо базу данных, мы можем проанализировать типы полей, в которые запи- сываются переменные программы. А потом проанализировать огра- ничения, которые накладывает база данных. Например, если вводимая фамилия пользователя записывается в поле типа «строка» длиной 128 символов, мы должны: 1) попробовать найти фамилию длиннее, чем 128 символов – здесь будет довольно серьезный баг, если такие фамилии сущест- вуют – человек с такой фамилией не сможет воспользоваться нашей системой; 2) вне зависимости от того, существуют или нет такие фами- лии, попробовать ввести строку длиннее 128 символов – программа не должна ломаться (должно показываться внятное сообщение об ошибке). Информация о других внешних системах Если программа интегрируется с другими внешними система- ми, помимо базы данных, можно также проанализировать ограни- чения таких систем. Например, если мы тестируем почтовый IMAP- клиент, следует убедиться, что он корректно обрабатывает длинные пути к папкам на сервере (чаще всего, ограничение на длину пути составляет 255 символов) Информация о коде программы Если мы имеем доступ к коду программы, мы можем |