|
| ||||||||||||
| ||||||||||||
|
2004 г.
Автоматизация процесса тестирования при помощи методологии и инструментальных средств IBM Rational. Часть IIИнструментальные средства поддержки процесса тестированияНовичков Александр, Костиков Александрwww.cmcons.com info@cmcons.com Часть первая - Введение в процесс тестирования Часть вторая — Инструментальные средства поддержки процесса тестирования Введение Инструментальные средства поддержки процесса тестированияВведениек оглавлениюПриведем список программных продуктов, рекомендованных к использованию в тестировании на разных этапах. Вот их наименования и краткое описание: Rational Quantify. Профилирование производительности; Программные продукты будут описаны в порядке применения в проектах. Сначала рассмотрим средства тестирования для разработчиков (Quantify, Purify, PureCoverage). Данные средства неразрывно связаны с языком реализации и со средой разработки. Примеры, приведенные в книги ориентированы на язык программирования С++ и частично на С#. В связи с тем, что на момент написания была доступна только бета-версия Visual Stu-dio .NET, то мы в основном ориентировались на версию 6.0, лишь изредка демонстрируя возможности новой среды. Тоже касается и языка реализации C#. Примеры его использования также будут встречаться, но все же основное внимание будет уделено языку реализации С++, имеющем наивысший рейтинг среди языков для реализации крупных программных систем. К сожалению, за бортом остались Java и Basic, но мы надеемся, что разработчики воспримут все написанное здесь как модель реализации, подходы которой совместимы со многими языками программирования. В следующей части перейдем к функциональному и нагрузочному тестированию. Начнем рассмотрение функционального тестирования с его планирования, чьи данные неразрывно связаны с требованиями, полученными на этапе определения требований к системе. Test Manager, в этом разрезе является как средством планирования тестирования, так средством реализации различных видов тестирования, так и средством предоставления финальной, пост — тестовой, отчетности. Далее воспользуемся продуктом Robot, который осуществляет физическую запись скриптов тестирования, с их последующим воспроизведением. Ознакомимся с визуальными и ручными режимами составления тестов посредством Robot. Научимся составлять как функциональные скрипты так и варианты нагрузочных скриптов. Рассмотрим различные режимы работы продукта. Для полного понимания возможностей, опишем основные синтаксические нотации скриптовых языков SQA Basic. В завершении опишем связи средств тестирования с остальными программными продуктами Rational. Средства тестирования для разработчиковк оглавлениюОрганизация тестированияк оглавлениюКак при приемочном тестировании, так и при регрессионном разработчик должен предоставить не только работающий код, удовлетворяющий начальным требованиям, но и делающий это максимально безукоризненно с точки зрения производительности и устойчивости. В дополнение, разработчик должен максимально тщательно проверить исполнение всех строчек написанного им кода, во избежание дальнейших несуразностей, ведь одна из часто встречаемых ошибок — это копирование блоков программного кода в разные части программы, при том, что не все ветви первоначального блока были обработаны и протестированы. Подобные первоначальные ошибки сводят на «нет» дальнейшее функциональное тестирование, так как низкокачественный код не позволяет тестерам быстро писать скрипт, реализующий тестирование новой формы, так как она полна странностей. Доработка, доработка, доработка... Интересная деталь: процессоры работают быстро, шины работают быстро, память тоже быстро, а вот программное обеспечение из года в год, от версии к версии работает все медленнее и медленнее, потребляя при этом на порядок больше ресурсов, нежели чем предыдущие версии. Не спасают положение даже оптимизирующие компиляторы! Вторая не менее интересная деталь заключается в скорости разработки. Вы не обращали внимания на то, что аппаратные продукты (процессоры и прочее) обновляются гораздо чаще и выпускаются с меньшим числом ошибок? Проблема кроется здесь в разных подходах к реализации программного кода в хардверных и софтверных компаниях. В софтверных компаниях, обычно, нет строго организованного процесса тестирования, нет строгой регламентации процесса кодирования, а сам процесс кодирования является особым видом искусства. То есть налицо пренебрежение основополагающими принципами промышленного производства, регламентирующими роли и процессы, входные и выходные значения. Из нашего опыта работы с партнерами мы знаем не понаслышке о жестких, и даже, жестоких требованиях к программному обеспечению, прошиваемому в аппаратуру, скажем так, у одной компании производителя сотовых телефонов есть требование, в соответствии с которым сотовому телефону «разрешается» зависнуть один раз в год при непрерывной эксплуатации. И это, не говоря о том, что все пункты меню соответствуют начальным требованиям на 100%. Вот и получается, что при вопросе: «Согласны ли вы, чтобы ваш телефон работал на основе обычной операционной системы (Windows, Unix... или им подобными)?», Традиционно следует — «нет»! Поскольку этап тестирования кода приложения можно отнести к тестированию «прозрачного ящика», когда важен код приложения, то мы попробуем описать основные рекомендации по тестированию для данного этапа, которые почерпаны из личного опыта и основаны на здравом смысле и принципах разумной достаточности. То есть, мы сначала рассмотрим общие требования к качеству кода, а потом проведем ассоциацию с инструментами Rational, которые позволят решить проблемы данного участка. Следующие недостатки (относительные) программного кода могут потенциально привести приложение к состоянию зависания (входа в вечный цикл) или к состоянию нестабильности, проявляемой время от времени (в зависимости от внешних факторов):
Quantify, Purify и PureCoverageк оглавлениюДля осуществления всех функций по тестированию программных модулей, все три продукта используют специальную технологию Object Code Insertion, при которой бинарный файл, находящийся под тестированием, насыщается отладочной бинарной информацией, обеспечивающей сбор информации о ходе тестирования. Отметим общие черты для всех трех программных продуктов. Для сбора и обработки информации программам тестирования нужны два файла: исполняемый модуль и его исходный текст. Исполняемый модуль насыщается отладочным кодом, а наличие исходного текста позволяет разработчику легко переключаться между схематическим отображением и кодом тестируемого приложения. На код накладываются дополнительные особые ограничения, а именно: тестируемый код должен быть получен при помощи компиляции с опцией «Debug», то есть должен содержать отладочную информацию. В противном случае Quantify, Purify и PureCoverage не смогут правильно отображать (вообще не смогут отображать) имена функций внутренних модулей тестируемого приложения. Исключения могут составлять только вызовы внешних модулей из dll-библиотек, поскольку метод компоновки динамических библиотек позволяет узнавать имена функций. Отсюда можно сделать простой вывод: тестировать приложения можно даже не имея отладочной информации в модуле и при отсутствии исходных текстов, но в этом случае разработчик получает статистику исключительно по внешним вызовам. Все три продукта способны проводить особые виды тестирования, такие как тестирование сервисов NT\2000\XP. Программные продукты могут работать в трех режимах:
Из дополнительных возможностей всех инструментов хочется отметить наличие специального набора файлов автоматизации, разрешающих разработчикам еще на этапе разработки внедрять С-образные вызовы функций сбора информации по тестированию в свои приложения, получая при этом максимальный контроль над ними. Средства анализа, строенные в Quantify, Purify и PureCoverage позволяют удовлетворить детально контролировать все нюансы в исполнении тестируемого приложения. Здесь и сравнение запусков, и создание слепков в ходе тестирования и экспорт в Excel для построения точных графиков множественных запусков. Особо хочется отметить языковую «всеядность» продуктов. Поддерживаются следующие языки программирования:
Профилировщик Quantifyк оглавлениюВведениек оглавлениюQuantify, вставляя отладочный код в бинарный текст тестируемого модуля, замеряет временные интервалы, которые прошли между предыдущим и текущими запусками. Полученная информация отображается в нескольких видах: табличном, графическом, комбинированном. Статистическая информация от Quantify позволит узнать какие dll библиотеки участвовали в работе приложения, узнать список всех вызванных функций с их именами, формальными параметрами вызова и с статистическим анализатором, показывающим сколько каждая функция исполнялась. Гибкая система фильтров Quantify позволяет, не загромождая экран лишними выводами (например, системными вызовами), получать необходимую информацию либо только о внутренних, программных вызовах либо только о внешних, либо комбинируя оба подхода. Вооружившись полученной статистикой, разработчик без труда выявит узкие места в производительности тестируемого приложения и устранит их в кратчайшие сроки.
Запуск приложенийк оглавлению
Рисунок 1 показывает действия после выбора «File->Run», в результате которого можно выбрать имя внешнего модуля и аргументы его вызова. В качестве параметров настройки можно выбрать метод вставки отладочного кода:
По умолчанию Quantify собирает статистическую информацию в модуле тестируемого продукта и во всех внешних библиотеках.
Начало насыщения тестируемого приложения сопровождается появлением окна инструментирования, в котором построчно отображаются все модули, вызываемые основным. Данные модули, как говорилось выше, насыщаются отладочным кодом и помещаются в специальную директорию «cache» по адресу «\rational\quantify\cache». Отметим, что первоначальный запуск инструментирвания процесс длительный, но каждый последующий вызов сокращает общее время ожидания в силу того, что вся необходимая информация уже есть в Кеше. С точки зрения дисковой емкости, файл (кэшируемый) с отладочной информацией от Quantify вдвое длиннее своего собрата без отладочной информации. Анализ информации«Run Summary»к оглавлениюПлавно переходим к следующей стадии тестирования, собственно, к сбору информации. По окончании процесса насыщения отладочным кодом модулей тестируемого приложения, Quantify переходит к его исполнению, производимым, обычным образом, за одним исключением: запись состояний тестируемого приложения продолжает проводиться в фоновом режиме.
Рисунок 3 демонстрирует фрагмент окна «Summary», в котором производится запись состояния тестируемого приложения. Причем, что очень примечательно, тестирование производится не только для простого приложения, но и для много поточного. В последнем случае (см. рисунок 3), тестируется каждый поток отдельно. В любом случае, даже если приложение однопоточное, то имя основного (единственного) потока именуется как «.main_0», что представляется вполне логичным. Информационный график постепенно наполняется квадратами разного цвета, демонстрирующими текущее состояние тестируемого приложения. Отметим некоторые из них:
Важный аспект при тестировании — получение статистической информации о количестве внешних библиотек, которые вызывало основное приложение, а также элементарное описание машины, на которой проводилось тестирование. Последнее особенно важно, так как бывает, что ошибка проявляется только на процессорах строго определенной серии или производителя. Все статистические аспекты решаются внутри окна «Summary». Следующие два примера показывают статистическую информацию: Program Name: C:\projects\aa\Debug\aa.exe (2) «Log» Для разработчика или тестера информация (информационный отчет), представленная выше, способна пролить свет на те статистические данные, которые сопровождали, а точнее, формировали среду тестирования. Дерево вызовов «Call Graph»к оглавлениюСледующий интереснейший способ анализа конструкции приложения — это просмотр дерева вызовов. Окно, показанное на 4 рисунке, показывает только фрагмент окна с диаграммой вызовов.
Обратите внимание на количество и последовательность вызова различных модулей потока «main». Жирная линия показывает наиболее длительные ветви (содержащие либо часто вызываемые функции, либо функции, выполнявшиеся дольше остальных). Для демонстрации возможностей Quantify было сконструировано простое приложение, состоящее из функции «main» и двух дополнительных «recursive» и «outside» (см. листинг 1). Листинг 1. Пример тестируемого приложения, сконструированном в виде консольного приложения из Visual Studio 6.0. Язык реализации «С». #include "stdafx.h" //Создаем функцию-заглушку //Создаем рекурсивную функцию, исполняющуюся 100 раз int main(int argc, char* argv[]) Приложение простое по сути, но очень содержательное, так как эффективно демонстрирует основные возможности Quantify. В самом начале статьи мы выдвигали требование, по которому разработчикам не рекомендуется пользоваться рекурсивными функциями. Тестеры или разработчики, увидев диаграмму вызовов, выделят функцию, находящуюся в полукруге, что является признаком рекурсивного вызова (см. рисунок).
В зависимости от того, на какой из ветвей дерева, находится курсор, выводится дополнительная статистическая информация о временном доступе к выделенной функции и к дочерним, идущим ниже. Следующий рисунок демонстрирует статистику по функции «recursive».
Более подробно о статистике будет рассказано в следующем материале. Список вызовов функций «Function List»к оглавлениюОдно из наиболее важных статистических окон. Здесь в табличном виде выводится статистическая информация по числу и времени работы каждой функции. Рисунок 6 демонстрирует окно с включенной сортировкой по числу вызовов каждой функции. В качестве дополнительной информации включен список формальных параметров вызовов функций. Подобную информацию можно получить только в том случае, когда тестируется модуль с отладочным кодом, к которому прилагается исходный текст. Единицы измерения длительности работы функций могут быть следующими:
На рисунке приведены цифры соответствующие машинным циклам.
Полученная таблица вызовов анализируется тестером или разработчиком для выяснения узких мест в производительности приложения. К сожалению, для принятия решения о производительности приложения, а точнее, производительности отдельных его функций можно принимать только рассматривая данный вопрос в комплексном разрезе. А именно, принимается во внимание и число вызовов каждой функции, и среднее время доступа к функции и общее время работы функции, и, наконец, то использовались ли при компиляции определенные специфические настройки компилятора. Это комплексный подход, не предполагающий однозначного совета. Сначала рассмотрим описание столбцов в появившейся таблице. Хотя многие из пунктов и являются интуитивно понятными, все же попробуем дать им короткое описание:
По любому из предложенных полей можно провести сортировку в прямом и обратном порядке, а также наложить фильтр на определенные модули, например, для проверки только внутренних модулей или только внешних. Выделить из списка узкую функцию трудно, поскольку для правильного расчета нужно принимать во внимание и время работы функции и число вызовов. Причем, число вызовов не всегда может быть показателем медлительности функции (вызывается часто, а работает быстро). Трудно давать какие либо советы по оптимизации кода, тем более, что в этой редакции мы не ставили перед собой подобных целей. По теории оптимизации написаны громадные труды, к которым мы с радостью и отправляем читателей. Можно, конечно, дать общие рекомендации по улучшению производительности кода и его эффективности: Использовать конструкцию «I++» вместо «I=I+1», так как компиляторы транслируют первую конструкцию в более эффективный код. К сожалению, этот эффективность примера ограничена настройками используемого компилятора, и иногда бывает равнозначной по быстродействию; Использовать прием развертывания циклов. Такой же старый прием оптимизации работы относительно простых циклов. Эффект заключается в сокращении числа проверок условия счетчика, так при проверке выполняются очень медленные функции микропроцессора (функции перехода). То есть вместо кода: For(i=0;i<100;i++)sr=sr+1; Лучше писать: For(i=0;i<100;i+=2) Использовать тактику отказа от использования вычисляющих конструкций внутри простых циклов. То есть, если иметь подобный фрагмент кода: for (sr = 0; sr < 1000; sr++) то его лучше преобразовать в такой: mn= x * y; поскольку мы избавляемся от лишней операции умножения в простом цикле; Там где возможно при работе с многомерными массивами, обращаться с ними как с одномерными. То есть, если есть необходимость в копировании или инициализации, например, двумерного массива, то вместо кода: int sr[400][400]; for (i = 0; i < 400; i++) лучше использовать конструкцию, в которой нет вложенного цикла: int sr[400][400]; for (int i = 0; i < 400*400; i++) Также при работе с циклами выгодно использовать слияния, когда несколько коротких однотипных циклов сливаются вместе. Подобный подход также дает прирост в производительности кода; В математических приложениях, требующих больших вычислений с плавающей точкой, или с большим количеством вызовов тригонометрических функций, удобно не производить все вычисления непосредственно, а использовать подготовленные значения в различных таблицах, обращаясь к ним как к индексам в массиве. Подход очень эффективен, но, к сожалению, как и многие эффективные подходы применим не всегда; Короткие функции в классах лучше оформлять встроенными (inline); В строковых операциях, в операциях копирования массивов лучше пользоваться не собственными функциями, а применять для этого стандартные библиотеки компилятора, так как эти функции, как правило, уже оптимизированы по быстродействию; Использовать команды SSL и MMX, поскольку в достаточно большом круге задач они способны дать ускорение работы приложений в разы. Под такие задачи попадают задачи по работе с матрицами и векторами (арифметические операции над матрицами и векторами); Использовать инструкции сдвига вместо умножений и делений там, где это позволяет делать логика программы. Например, инструкция S=S<<1 всегда эффективнее, чем S=S*2; Конечно, это далеко не полный список приемов оптимизации кода по производительности и качеству. Для этого есть масса других книг. Примеры здесь имеют чисто утилитарный подход: демонстрация возможностей Quantify в плане исследования временных характеристик кода. Используя все средства сбора и отображения, разработчик постепенно сможет использовать только эффективные конструкции, что поднимет производительность на недосягаемую ранее высоту. По любой функции можно вывести более детальный отчет (см. рисунок). Из него можно почерпнуть информацию о числе дочерних функций и то, откуда они были произведены. Следующий рисунок демонстрирует данную возможность.
Переход к просмотру исходного текста. Если тестируемый модуль сопровождается исходным текстом, то в Quantify имеется возможность по переходу на уровень просмотра исходного текста. По контекстному меню можно осуществить данный переход. Вызывать функцию перехода имеет смысл только в том случае, когда Quantify работает в независимом режиме, в отрыве от среды разработки. Рисунок демонстрирует данный режим. Сравнивание запусков «Compare Runs»к оглавлениюВ большинстве случаев требуется иметь не только сведения об отдельных запусках, но и сравнения разных запусков в различных комбинациях для прогнозирования и анализа. Ведь всегда интересно знать быстро работает исправленная функция или медленно, по сравнению с тем, что было до этого. Подобная аналитическая информация позволить иметь достаточно четкое представление о том находятся ли функции в прогрессирующем или в регрессирующем состоянии.
Для вызова модуля сравнения необходимо воспользоваться кнопкой (Compare Runs), выделив один из запусков, и указав на любой другой (каждый новый запуск отображается в истории запусков на левой части рабочего поля Quantify). Для осуществления не пустого сравнения, в пример, рассмотренный выше, намеренно были внесены изменения, увеличившие число вызовов функций. Данные были сохранены и перекомпилированы и снова исполнены в Quantify. Результат представлен на рисунке:
Сравнение запусков позволяет проводить сравнительный анализ между базовым запуском (base – том, с которого все началось) и новым (new). Результаты сравнения также остаются в проекте Quantify и сохраняются на протяжении жизненного цикла разработки проектов. Наравне со сравнением запуск можно воспользоваться суммированием, нажав на кнопку Можно сравнивать и складывать также запуски вместе со слепками (snapshot), которые позволяют оформить текущее количественное состояние в работе приложения в виде отдельного запуска. В дальнейшем над ним можно провести любую логическую операцию. Ценность слепков проявляется тогда, когда необходимо узнать число вызовов каждой функции до свершения определенного события, например, до входа в определенный пункт меню в тестируемом приложении. APIк оглавлениюЭто дополнительная возможность, предоставляемая Quantify по полному управлению процессом тестирования. API представляет собой набор функций, которые можно вызывать из тестируемого приложения по усмотрению разработчика. Для получения доступа к API необходимо выполнить ряд действий по подключению «puri.h» файла с определением функций и с включением «pure_api.c» файла в состав проекта. Единственное ограничение, накладываемое API — рекомендации по постановке точек останова после вызовов Quantify при исполнении приложения под отладчиком. Рассмотрим имеющиеся функции API Quantify:
Если модифицировать наше тестовое приложение так, чтобы оно использовало преимущества интерфейса API, то может получиться нечто нижеследующее int main(int argc, char* argv[]) QuantifyAddAnnotation("Тестирование проводится под Quantify с использованием API"); В листинге показано как можно использовать основные функции API для извлечения максимального статистического набора данных. Рисунки показывают слепки фрагментов экрана Quantify по окончании тестирования.
Рис. Данный рисунок демонстрирует вид окна после выполнения команды снятия слепка или вызова функции API QuantifySaveData()
Рис. Обратите внимание на поле аннотации
Рис. У Quantify отсутствуют сложности с русскими буквами Сохранение данных и экспорт | к оглавлениюТрадиционные операции над файлами присущи и программе Quantify. Дополнительные особенности заключаются в том, что сохранять данные можно как во встроенном формате (qfy), для каждого отдельного запуска, так и в текстовом виде, для последующего использования в текстовых редакторах, либо для дальнейшей обработки скриптовыми языками типа perl (более подробно смотрите об этом в разделах по ClearCase и ClearQuest). Quantify позволит переносить таблицы через буфер обмена в Microsoft Excel, что открывает безграничные возможности по множественному сравнению запусков, по построению графиков и различных форм. Все что необходимо сделать — это только скопировать данные из одной программы и поместить в другую известным способом. Purify. Контроль над утечками памятиВведениек оглавлениюНачать описание возможностей продукта Rational Purify хочется перефразированием одного очень известного изречения: «с точностью до миллиБАЙТА». Данное сравнение не случайно, ведь именно этот продукт направлен на разрешение всех проблем, связанных с утечками памяти. Ни для кого не секрет, что многие программные продукты ведут себя «не слишком скромно», замыкая на себя во время работы все системные ресурсы без большой на то необходимости. Подобная ситуация может возникнуть вследствие нежелания программистов доводить созданный код «до ума», но чаще подобное происходит не из за лени, а из-за невнимательности. Это понятно — современные темпы разработки ПО в условиях жесточайшего прессинга со стороны конкурентов не позволяют уделять слишком много времени оптимизации кода, ведь для этого необходимы и высокая квалификация, и наличие достаточного количества ресурсов проектного времени. Как мне видится, имея в своем распоряжении надежный инструмент, который бы сам в процессе работы над проектом указывал на все черные дыры в использовании памяти, разработчики начали бы его повсеместное внедрение, повысив надежность создаваемого ПО. Ведь и здесь не для кого не секрет, что в большинстве сложных проектов первоочередная задача, стоящая перед разработчиками заключается в замещении стандартного оператора «new» в С++, так как он не совсем адекватно себя ведет при распределении памяти. Вот на создании\написании собственных велосипедов и позволит сэкономить Purify. Рисунок демонстрирует внешний вид программы после проведения инструментирования (тестирования) программного модуля.
Общие возможности по управлению Purify схожи с Quantify, за исключением специфики самого продукта. Здесь также можно тестировать многопоточные приложения, также можно делать «слепки» памяти во время тестирования приложения. Особенности использования данного приложения касаются спецификой отлавливаемых ошибок и способом выдачи информации. Информация выдается в виде списке, с наименованием найденной ошибки или предупреждения. При разворачивании списка с конкретной ошибкой выводится дополнительный набор данных, характеризующих ошибку. Основные параметры вывода | к оглавлению
Работа с Purify возможна как при наличии исходных текстов и отладочной информации, так и без нее. В случае отсутствия debug-информации анализ ошибок ведется только по ip-адресам. Так же как и в случае с Quantify, возможен детальный просмотр функций из dll-библиотек. В этом случае наличие отладочной информации не является необходимостью. Сообщения об ошибках и предупрежденияхк оглавлениюДля того, чтобы иметь представление о возможностях продукта, опишем то, какие ошибки и потенциальные ошибки могут присутствовать в тестируемом приложение. Отметим разницу между ошибкой и потенциальной ошибкой и опишем:
Естественно, что подобное поведение может быть вызвано спецификой приложения, например, так вести себя может текстовый редактор. Поэтому в Purify применятся деление информации на ошибки и потенциальные ошибки (которые можно воспринимать как специфику). Список ошибок и потенциальных ошибок достаточно объемен и постоянно пополняется. Кратко опишем основные сообщения, выводимые после тестирования:
Предупреждения и ошибки удобно группировать по определенным признакам, чтобы легче можно было отыскать нужное предупреждение и отбросить ненужные. Отметим категории и принадлежность к ним различных сообщений:
Многие статические ошибки могут вылавливать компиляторы на этапе разработки программного модуля или приложения. На этом этапе преимущества Purify не очень видны. Все механизмы анализа ошибок открываются при исполнении приложения, при динамически меняющихся условиях. Рассмотрим более подробно список отлавливаемых ошибок, определив их принадлежность к категориям с примерами на C++/C: ABR: Array Bounds Read. Выход за пределы массива при чтении. Известная болезнь всех разработчиков — неправильно поставленное условие в цикле. Соответственно, ошибка, которая имеет место быть в программе, связанная с чтением лишней информации, может проявить себя, а может и не проявить. Но она является потенциальной ошибкой. #include <iostream.h> ptr[0] = ‘e’; ABW: Array Bounds Write. Выход за пределы массива при записи Вероятность того, что приложение может неадекватно вести себя из-за данной ошибки более высоко, так как запись по адресу, превышающим размер блока, вызывает исключение. Отметим, что память можно определить статически, массовом, как показано в примере. А можно динамически (например, выделив блок памяти по ходу исполнения приложения). По умолчанию, Purify успешно справляется только с динамическим распределением, четко выводя сообщение об ошибке. В случае статического распределения, все зависит от размеров «кучи» и настроек компилятора. #include <iostream.h> ABWL: Late Detect Array Bounds Write. Cообщение указывает, что программа записала значение перед началом или после конца распределенного блока памяти #include <iostream.h> BSR: Beyond Stack Read. Сообщение указывает, что функция в программе собирается читать вне текущего указателя вершины стека Категория: Stack Error #include <windows.h> int main(int, char **) cerr << "element #" << i << " is " << block[i] << '\n'; FFM: Freeing Freed Memory. Попытка освобождения свободного блока памяти. В большом приложении трудно отследить момент распределения блока и момент освобождения. Очень часто методы реализуются разными разработчиками, и, соответственно, возможна ситуация, когда распределенный блок памяти освободается дважды в разных участках приложения. Категория: Allocations and deallocations #include <iostream.h> FIM: Freeing Invalid Memory. Попытка освобождения некорректного блока памяти. Разработчики часто путают простые статические значения и указатели, пытаясь освободить то, что не освобождается. Компилятор не всегда способен проанализировать и нейтрализовать данный вид ошибки. Категория: Allocations and deallocations #include <iostream.h> int main(int, char **) FMM: Freeing Mismatched Memory. Сообщение указывает, что программа пробует освобождать память с неправильным ВЫЗОВОМ API для того типа памяти Категория: Allocations and deallocations #include <windows.h> int main(int, char **) HeapDestroy(heap_first); FMR: Free Memory Read. Попытка чтения уже освобожденного блока памяти Все та же проблема с указателем. Блок распределен, освобожден, а потом, в ответ на событие, по указателю начинают записываться (или читаться) данные. Категория: Invalid pointers #include <iostream.h> FMW: Free Memory Write. Попытка записи уже освобожденного блока памяти Категория: Invalid pointers #include <iostream.h> HAN: Invalid Handle. Операции над неправильным дескриптором Категория: Invalid handles #include <iostream.h> HIU: Handle In Use. Индикация утечки ресурсов. Неправильная индикация дескриптора. #include <iostream.h> cerr << "Ошибка открытия, создания файла\n"; if (ptr == NULL) { IPR: Invalid Pointer Read. Ошибка обращения к памяти, когда программа пытается произвести чтение из недоступной области Категория: Invalid pointers #include <iostream.h> #include <windows.h> for (int i=0; i < 2; i++) { IPW: Invalid Pointer Write. Ошибка обращения к памяти, когда программа пытается произвести запись из недоступной области Категория: Invalid pointers #include <iostream.h> for (int i=0; i < 2; i++) { MAF: Memory Allocation Failure. Ошибка в запросе на распределение памяти. Возникает в случаях, когда производится попытка распределить слишком большой блок памяти, например, когда исчерпан файл подкачки. Категория: Allocations and deallocations #include <iostream.h> MLK: Memory Leak. Утечка памяти Распространенный вариант ошибки. Многие современные приложения грешат тем, что не отдают системе распределенные ресурсы по окончании своей работы. Категория: Memory leaks #include <windows.h> MPK: Potential Memory Leak. Потенциальная утечка памяти Категория: Memory leaks #include <iostream.h> NPR: Null Pointer Read. Попытка чтения с нулевого адреса Категория: Invalid pointers #include <iostream.h> NPW: Null Pointer Write. Попытка записи в нулевой адрес Категория: Invalid pointers #include <iostream.h> UMC: Uninitialized Memory Copy. Попытка копирования непроинициализированного блока памяти Категория: Unitialized memory #include <iostream.h> int main(int, char **) } UMR: Uninitialized Memory Read. Попытка чтения непроинициализированного блока памяти Категория: Unitialized memory #include <iostream.h> Работа с фильтромк оглавлениюЧтобы не загромождать пользовательский интерфейс лишними данными, в Purify предусмотрена система гибких фильтров. Система фильтров Purify способна регламентировать тип ошибок и предупреждений и ошибок (группировка производится по категориям) к программе, но и число исследуемых внешних модулей (чтобы разработчик мог концентрироваться только на ошибках собственного модуля). Таким образом возможно создание универсальных фильтров с осмысленными именами, которые ограничивают поток информации. Число создаваемых фильтров ничем не ограничено. Фильтры создаются и назначаются и модифицируются через верхнее меню (View->CreateFilter и View->FilterManager). По умолчанию Purify выводит все сообщения и предупреждения.
Рисунок показывает внешний вид окна создания фильтра (View->CreateFilter). Здесь мы имеем возможность по выбору сообщений, которые нужно отфильтровывать. Пункт General — управляет именем фильтра и комментарием, его сопровождающим, Source — определяет местоположение исходных файлов, для которых необходимо вывести сообщения. Подход используется в том случае, когда происходит вызов одного модуля из другого, дабы ограничить количество информации в отчете. Следующий рисунок демонстрирует вид окна настроек фильтров. Здесь имеется возможность по активации\деактвации фильтров и модулей.
Выше упоминалось, что Purify не ограничивает число фильтров. Следует понимать, что не ограничивается не только общее число фильтров, но и их количество на одно протестированное приложение. Ограничение по модулям, которое также можно выставить в данном диалоге, определяет число внешних модулей, предупреждения от которых появляются в отчете. API | к оглавлениюRational Purify также имеет ряд функций интерфейса, воздействуя на которые, разработчик на этапе создания приложения может пользоваться всеми благами, предоставляемые данным приложением. Опишем основные функции интерфейса с краткой характеристикой, разделив предварительно все функции по основным группам: Функции установки статуса распределенных блоков:
Функции тестирования состояний распределенных блоков
Функции, определяющие разрушения
Функции, определяющие утечки памяти
Сохранение данных и экспортк оглавлениюPurify позволяет сохранять результаты тестирования (file->save copy as) в четырех различных представлениях, позволяющих наиболее эффективным образом получить информацию о ходе тестирования. Рассмотрим варианты сохранения:
При установленном MS Outlook, возможно отправление отчета почтой через пункт file->send из верхнего меню Purify. Параметры тестированияк оглавлениюПеред исполнением тестируемого приложения, возможно, задать дополнительные настройки, которые смогут настроить Purify на эффективное тестирование. Запуск приложения производится точно также как и в случае с Quantify (по F5 или file->Run). Параметры настройки находятся пункте Settings, появившегося окна. Первая страница диалога представлена на рисунке
Отметим основные особенности, которые качественно могут сказаться на результирующем отчете:
Закладка PowerCheck позволит настроить уровень анализа каждого отдельно взятого модуля. Существует два способа инструментирования тестируемого приложения: Precise и Minimal. В первом случае проводится детальное инструментирование кода, но при этом модуль работает относительно медленно. Во втором случае, проводится краткое инструментирование, при котором Purify вносит в модуль меньше отладочной информации, и, как следствие, способна отловить меньшее число ошибок. Последний подход оправдан, когда приложение вызывает массу внешних библиотек от третьих фирм, которые не будут подвергаться правке. PureCoverage. Проверка области охвата кодаВведениек оглавлениюОсновное назначение продукта — выявление участков кода, пропущенного при тестировании приложения — проверка области охвата кода. Очевидно, что при тестировании разработчику или тестировщику не удастся проверить работоспособность абсолютно всех функций. Также невозможно за один проход тестирования исполнить приложение с учетом всех условных ветвлений. По требованиям на разработку программного кода, программист должен предоставить для функционального тестирования стабильно работающее приложение или модуль, без утечек памяти и полностью протестированный. Понятие «полностью протестированный» определяет руководство компании в числовом, процентном значении. То есть, при оформлении требований указано, что область охвата кода 70%. Соответственно, по достижении данной цифры дальнейшие проверки кода можно считать нецелесообразными. Конечно, вопрос области охвата, очень сложный и неоднозначный. Единственным утешением может служить то, что 100% области охвата в крупных проектах не бывает. Из трех рассматриваемых инструментов тестирования PureCoverage можно считать наиболее простым, так как информация им предоставляемая — это просмотр исходного текста приложения, где указано сколько раз исполнилась та или иная строка в приложении. Особенности запуска | к оглавлениюЗапуск приложения ведется точно таким же образом, как и в остальных случаях. Здесь нового ничего нет. Из особенностей можно отметить то, что тестировать можно только то приложение, которое содержит отладочную информацию. Данная особенность выделяет PureCoverage из линейки инструментов тестирования для разработчиков, которые могут тестировать как код с отладочной информацией, так и без нее. При попытке исполнить приложение, не содержащее отладочной информации, на экран, по окончании тестирования, будет выведено сообщение об ошибке. Работа с PureCoverage | к оглавлениюПо принципу работы PureCoverage слегка напоминает Quantify: также подсчитывает количество вызовов функций. Правда, получаемая статистика не столь исчерпывающая как в Quantify (в визуальном отношении), но для проверки области охвата кода вполне и вполне пригодна. Система отчетности представлена 4-я различными видами отчетов:
Анализ результатов тестирования | к оглавлениюНа рисунке показана статистическая выкладка, выведенная Coverage по окончании тестирования приложения.
Поле Calls определяет число вызовов функции Из полученной таблицы видна статистическая информация о том, какие строки и сколько раз исполнялись. К особенностям работы PureCoverage отнесем тестирование только тех исполняемых файлов, которые уже имеют отладочную информацию от компилятора. Соответственно, тестирование стандартных приложений и библиотек данным продуктом невозможно. Впрочем, и не нужно. Особые преимущества инструмент демонстрирует при совместном тестировании с Robot при функциональном тестировании, подсчитывая строки исходных текстов в момент воспроизведения скрипта. Тем самым на выходе тестировщик (или разработчик) получает информацию о стабильности функциональных компонент, плюс, область покрытия кода (область охвата).
Поле %Lines Hit показывает процентное отношение протестированных строк кода для отдельной функции.
Вид окна перехода на уровень работы с исходным текстом. Из него видно, что PureCoverage ведет нумерацию строки и подсчитывает число исполнений каждой. Не исполнившиеся фрагменты подсвечиваются красным цветом (палитра может регулироваться пользователем) APIк оглавлениюКак и Quantify с Purify, данный инструмент имеет функции расширения интерфейса. Рассмотрим их краткое описание.
Сохранение данных и экспорт | к оглавлениюДанные из инструмента тестирования сохраняются в текстовом файле (как и в двух предыдущих случаях). Текстовый формат выдачи информации делает возможным включать различные обработчики отчетов основанные на скриптовых языках (например, при помощи Perl, можно «выудить» специфичные поля из текстового отчета и поместить их в средство документирования, получив отчет). Пример фрагмента отчета приведен ниже: CoverageData WinMain Function D:\xp\Rational\Coverage\Samples\hello.c D:\xp\Rational\Coverage\Samples\hello.exe 0 1 1 100.0 5 5 10 50.00 36 1 SourceLines D:\xp\Rational\Coverage\Samples\hello.c D:\xp\Rational\Coverage\Samples\hello.exe PureCoverage также как и Quantify может переносить табличные данные в Microsoft Excel. Итог | к оглавлениюДанный инструмент представляется наиболее простым из трех. Основное его отличие невозможность работы с приложениями, в которых отсутствует отладочная информация. Из достоинств отметим возможность одновременного запуска совместно с Purify, что позволяет получить отчеты по утечкам памяти и подсчет числа строк за один проход в тестировании, что существенно экономит время при отладке и тестировании. Дополнительные возможности средств тестирования для разработчиковСпособы запускак оглавлениюВсе инструментальные средства могут работать на 3 уровнях исполнения:
Тестирование сервисов Windows NT/2000/XPк оглавлениюОдно из важных преимуществ перед конкурентами — возможность тестирования специальных приложений, таких как сервисы. собенность работы заключается в том, что сервис нельзя запускать из среды разработки. Инструменты тестирования понимают это, и предлагают свое решение, по которому необходимо насытить код откомпилированного сервиса (с отладочной информацией) отладочной информацией (не запустив при этом). Полученные в результате файл зарегистрировать в качестве сервиса. Сделать это можно как из GUI так и из командной строки. Мы рассмотрим последовательность шагов для командной строки, демонстрируя ее возможности (в примере, используется ссылка на Purify, но вместо него подставить имя любого средства тестирования):
По окончании действий, в зависимости от типа операционной системы, необходимо перезапустить сервис или перезагрузить компьютер и запустить сервис. В момент старта сервиса инструмент тестирования запустится автоматически. Поскольку специальные программные средства могут не иметь графической оболочки, то для их детальной проработки рекомендуется использование функций API из инструментов тестирования для разработчиков. Основные свойства средств Purify, Quantify и PureCoverageк оглавлению
|
|
CITForum © 1997–2025