Реферат на тему «Тестирование обьектно-ориентированного програм

Реферат

на тему:

«Тестирование обьектно-ориентированного программного обеспечения»

Подготовил:

Студент. гр. МСС-5

Головко С. А.

Проверил:

Доцент кафедры ТТП

Бойко Б. И.

Киев 2006

Оглавление.

1. Вступление. 3.

2. Выбор тестовых случаев. 4.

3. Тестирование коллекций. 7.

4. Тестирование наследования.8.

5. Тестирование взаимодействующих классов. 10.

6. Выводы. 12.

7. Литература. 13.

Вступление.

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

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

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

Выбор тестовых случаев.

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

Спецификация класса Velocity предусматривает выполнения операции, которая называется setDirection(const Direction &newDirection), предусловия которого требует, чтобы атрибут newDirection принимал значения в пределах от 0 до 359 включительно. Сначала мы генерируем тестовые данные для этого метода, используя спецификацию в качестве основы. Прежде всего обратите внимание на то обстоятельство, что Direction есть typedef для int, следовательно, выбор будет проводится из набора целых чисел а не из набора объектов. Вместо выбора из каждого случая использования (от 0 до 359), сначала выбираются значения, основанные на граничных значениях. Таким образом, в окрестности граничного значения, равного нулю, мы имеем три значения, скорее всего, это -1, 0 и 1. Такой же набор тестовых значений должен быть выбран и для другой граничной точки, возможно это 358, 359 и 360. Должны быть также выбраны тесты в диапазоне от 1 до 358, именно в этом случае в наибольшей степени проявляются преимущества выборки. Значения в обоих интервалах можно выбрать, воспользовавшись формулами вида int(random() * 360) и int(-1 * random() * 360).

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

Ортогональная матрица позволяет получить особый метод выборки, способный ограничить последствия комбинаторного взрыва за счет объявления попарных сочетаний некоторого множества взаимодействующих объектов. Большинство отказов, возникающих при взаимодействиях, обусловлены двусторонними взаимодействиями. Одним из инструментов выборки образцов есть система OATS(Orthogonal Array Testing System — система тестирования с использованием ортогональной матрицы). Для применения этого метода не обходимо что бы у программы были независимые наборы состояний. Задача состоит в спаривании каждого состояния из одного набора со всеми состояниями из другого набора, по крайней мере один раз. Рассмотрим более детально применения этого метода на примере.

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

Книга

Закупка

Доставка

в_наличии_на_складе

наличные

срочная

специальный_заказ

чек

экономная

распродана

долговое обязательство

по месту

задержка

Табл.1

У каждого из двух клас сов есть три состояния а у одного класса их четыре, так что тестирование каждой комбинации потребует 3*3*4 = 36 тестовых примеров. Если выбрать состояния из двух классов то потребуется только 12 тестовых примеров, показанных в табл.2, и, следовательно, число необходимых тестових примеров уменьшится.

Тестовый пример

Книга

Закупка

Доставка

1

в_наличии_на_складе

наличные

срочная

2

в_наличии_на_складе

чек

экономная

3

в_наличии_на_складе

долговое обязательство

по месту

4

в_наличии_на_складе

наличные

задержка

5

специальный_заказ

чек

срочная

6

специальный_заказ

долговое обязательство

экономная

7

специальный_заказ

наличные

по месту

8

специальный_заказ

чек

задержка

9

Рас продана

долговое обязательство

срочная

10

Рас продана

наличные

экономная

11

Рас продана

чек

по месту

12

Рас продана

долговое обязательство

задержка

Табл.2

Рассматривая в таблице только столбцы Книги и Доставка (игнорируя столбец Закупка), можно увидеть все возможные комбинации этих двух классов. Аналогично, игнорируя класс книга, прослеживаются все возможные комбинации состояний закупки и доставки. У класса доставка больше состояний, чем у остальных двух классов, поэтому инспектирование спариваний столбцов Книга и Закупка указывает на то что все возможные комбинации дублируются. Один из случаев дублирования представлен тестовыми примерами 1 и 4.

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

Тестирование ортогональной матрицы – это мощный метод, который используется, после того как для каждого объекта ограничили число состояний в которых он может находится. Это систематизированный способ уменьшения числа тестовых случаев. Если позже мы решим выполнить дополнительные тесты, мы будем точно знать, какие сочетания не подвергать тестированию. Это также логический способ уменьшения тестовых случаев. Большая часть ошибок обнаруживается при взаимодействии пар объектов, а не при взаимодействии нескольких объектов. Таким образом мы проводим тестирование, в котором ошибки проявляются с большей вероятностью.

Тестирование коллекций.

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

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

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

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

Тестирование наследования.

При наследовании создаются новые классы, которые повторно используют и расширяют классы, созданные ранее. При этом допускается расширение функций существующего кода без реальной модификации исходного кода. Эта мощная концепция программирования вызывает некоторые проблемы при тестировании ПО. Производительный класс, или потомок родительского класса, наследует те же возможности, которые есть и у исходного класса, хотя при этом также добавляются его собственные возможности. Основная идея заключается в том, что после написания и отлажывания родительского класса никто не захотеть менять код из опасения внести новые ошибки. Еще одна причина использования наследования – возможное отсутствие доступу к исходному коду (это происходит, когда код распространяется в виде части библиотеки классов). Разработчик может также сделать наследование частью исходного проектирования. Точное определение момента, когда следует использовать наследование, является одним из аспектов хорошего обьектно-ориентированного программирования. Неуместное использование наследования, как и любой другой техники написания кода, может усложнить процесс тестирования и отладки.

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

Рассмотрим характерный пример. Есть класс А, класс Б – потомок класса А, класс В – потомок класса А и класса Б. Можно предложить, что методы класса А будут работать и тогда когда они вызваны объектом класса Б. Таким образом, трестировать нужно взаимодействия класса А в контексте класса Б. Аналогично нужно тестировать взаимодействия класса А в контексте класса В и взаимодействия Б в контексте В. Ошибки, как правило, возникают во взаимодействиях по мере перемещения вверх и вниз в иерархии уровней классов.

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

Тестирование взаимодействующих классов.

Тестирование взаимодействующих классов сопряжено с большими трудностями, нежели тестирование коллекций или примитивных классов. Рассмотрим пример. Класс BrickPile (куча кирпичей) из приложения «Кирпичики». Куча кирпичей – это агрегация кирпичей уложенных в прямоугольный штабель. Класс BrickPile подобен коллекции, в то же время BrickPile посылает семантически содержательное сообщение отдельным объектам Brick, например, чтобы определить местоположение конкретного кирпичика в игровом поле либо разрушить тот или иной кирпич. Отладка класса BrickPile возможна без использования экземпляров класса Brick. В то же время трудно обнаружить ошибки в BrickPile, если в классе Brick не выявлены некоторые типы ошибок. На кучу кирпичей возложена обязанность обнаружение соударений содержащихся в ней кирпичей с подвижными спрайтами (а именно, с шайбами), однако в ее задачу не входит обработка этих соударений. Она также регистрирует подсказки, связанные с разрушением кирпичей, с тем чтобы объект представления игры «Кирпичики» эффективно обновлял экран.

Для тестирования класса BrickPile потребуется задействовать один или большее число экземпляров этих классов. По существу, экземпляр BrickPile не может быть построен без участия экземпляров классов PlayField, CPoint, Hint поскольку они должны быть переданы конструктору как параметры. Разумеется ему понадобится также класс Brick, чтобы построить щабель кирпичей.

CPoint, Hint, Brick — примитивные классы и в силу этого обстоятельства могут быть протестированы с применением методов, которые назначены для тестирования примитивных классов. Класс CPoint, используется в игре Кирпичики является одним из классов MFC(Microsoft Foundation Class) и, следовательно, вызывает некоторое доверие, поэтому трестировать его нет необходимости. Классы PlayField и BrickPile не относятся к числу примитивных и должны подвергаться тестированию в контексте их взаимодействия с программными кодами других классов.

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

Например, рассмотрим следующую спецификацию метода broken() класса BrickPile, в рамках которого куча кирпичей взаимодействует с объектами класса Brick. Следует воспользоваться тестовым случаем, в котором brick_p указывает на конкретный экземпляр кирпича, и этот тестовый случай должен четко продемонстрировать факт удовлетворения постусловий.

В процессе тестирования класса BrickPile нам понадобится тестовые случаи, которые осуществляют взаимодействие с классом PlayField. В этом контексте в тестовом наборе должен быть тестовый случай, в условиях которого классу BrickPile поступает команда разрушить конкретный кирпичик, который уже был разрушен. Этот тестовый случай проводит проверку с целью убедится, что PlayField сам проводит проверку и в нарушение постусловий не отправляет сообщение broken() экземпляру PlayField.

Выводы.

Тестирование программного обеспечения – это отдельная дисциплина, требующая специальных навыков. Тестирование программного продукта не интуитивно; кто-то должен знать как это делается. Кроме того как показывает ниже изложенный материал тестер должен четко разбираться в основах обьектно-ориентированого программирование. Хотя, следует заметить, иметь практические навыки программирования тестеру не обязательно.

В условиях сегодняшнего рынка использовать для тестирования программного обеспечения программиста – дорого, но использовать – неопытных тестеров, тестеров которые только то и умеют, что тыкать на клавиши и смотреть с удивлением на результаты программы, — это вдвойне дорого. Использование команды тестеров ( для великих компаний ) или аутсорсинговых компаний, которые надают услуги по тестированию программного обеспечения повысит надежность ваших программ, поможет вам избежать непредсказуемых ситуаций – когда к дате завершения проекта у вас паника в компании( у программы выявлены новые «глюки», а времени на решения проблемы нет).

ВЫБОР ЗА ВАМИ!!!

Литература.

[1]. Макгрегор Джон, Сайка Девид. Тестирование обьектно-ориентированого программного обеспечения. Практическое пособие. – М. Торг. – изд. дом «DiaSoft», 2002.

[2]. Луиза Тампе. Введение в тестирование программного обеспечения. – М. Изд. дом. «Вільямс», 2003.

[3]. Сэм Канер, Джек Фолк, Енг Кек Нгуен. Тестирование программного обеспечения. Фундаментальные концепции менеджмента бизнес-приложений. – М. Торг. – изд. дом «DiaSoft», 2001.

[4]. Винниченко Илья Викторович. Автоматизация процессов тестирования. – П., 2005.