Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Темы на модуль(лекции).doc
Скачиваний:
0
Добавлен:
25.11.2019
Размер:
378.37 Кб
Скачать

Розділ 1 Структурне тестування програмного забезпечення

Лекція 1 (2 години)

Тема: Вступ. Основні поняття та принципи тестування програмного забезпечення

Концепція тестування. Основні принципи.

Налагодження (debug, debugging) - процес пошуку, локалізації й виправлення помилок у програмі. Термін " налагодження " у вітчизняній літературі використовується подвійно: для позначення активності по пошуку помилок (власне, тестування ), по знаходженню причин їхньої появи й виправленню, або активності по локалізації й виправленню помилок.

Тестування забезпечує виявлення (констатацію наявності) фактів розбіжностей з вимогами (помилок). Як правило, на фазі тестування здійснюється й виправлення ідентифікованих помилок, що включає локалізацію помилок, знаходження причин помилок і відповідне коректування програми додатку, що тестується (Application Under Testing (AUT) або Implementation Under Testing (IUT)).

Якщо програма не містить синтаксичних помилок (пройшла трансляцію) і може бути виконана на комп'ютері, вона обов'язково обчислює яку-небудь функцію, що здійснює відображення вхідних даних у вихідні. Це означає, що комп'ютер на своїх ресурсах довизначає частково визначену програмою функцію до тотальної визначеності. Отже, судити про правильність або неправильність результатів виконання програми можна, тільки порівнюючи специфікацію бажаної функції з результатами її обчислення, що й здійснюється в процесі тестування.

Основна термінологія та основні поняття

Тестування - процес виконання програми з метою виявлення помилок. Кроки процесу задаються тестами.

Кожний тест визначає:

- свій набір вихідних даних і умов для запуску програми;

- набір очікуваних результатів роботи програми.

Інша назва тесту — тестовий варіант. Повну перевірку програми гарантує вичерпне тестування. Воно вимагає перевірки всі набори вихідних даних, всі варіанти їхньої обробки й включає велику кількість тестових варіантів. На жаль, вичерпне тестування в багатьох випадках залишається тільки мрією - спрацьовують ресурсні обмеження (насамперед, обмеження за часом).

Гарним вважають тестовий варіант із високою ймовірністю виявлення ще не розкритої помилки. Успішним називають тест, що виявляє дотепер не розкриту помилку.

Метою проектування тестових варіантів є систематичне виявлення різних класів помилок при мінімальних витратах часу й вартості.

Тестування забезпечує:

- виявлення помилок;

- демонстрацію відповідності функцій програми її призначенню;

- демонстрацію реалізації вимог до характеристик програми;

- відображення надійності як індикатора якості програми.

Тестування не може показати відсутності дефектів (воно може показувати тільки присутність дефектів). Важливо пам'ятати це (скоріше сумне) твердження при проведенні тестування.

Тестування розділяють на статичне й динамічне:

  • статичне тестування виявляє формальними методами аналізу без виконання програми невірні конструкції або невірні відносини об'єктів програми (помилки формального завдання) за допомогою спеціальних інструментів контролю коду - CodeChecker. Також його називають тестуванням методами „чорного ящика”.

  • динамічне тестування (власне тестування ) здійснює виявлення помилок тільки на програмі, що виконується, за допомогою спеціальних інструментів автоматизації тестування. Цей вид тестування також називають методами „білого ящика ”(у деякій літературі – „прозорого”).

Інформаційні потоки процесу тестування

Розглянемо інформаційні потоки процесу тестування. Вони показані на мал. 1.1.

Мал. 1.1. Інформаційні потоки процесу тестування

На вході процесу тестування три потоки:

- текст програми;

- вихідні дані для запуску програми;

- очікувані результати.

Виконуються тести, всі отримані результати оцінюються. Це значить, що реальні результати тестів порівнюються з очікуваними результатами. Коли виявляється розбіжність, фіксується помилка - починається налагодження. Процес налагодження непередбачений за часом. На пошук місця дефекту й виправлення може знадобитися година, день, місяць. Невизначеність у налагодженні приводить до великих труднощів у плануванні дій.

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

- якість і надійність ПЗ задовільні;

- тести не здатні виявляти серйозні помилки.

В остаточному підсумку, якщо тести не виявляють помилок, з'являється сумнів у тім, що тестові варіанти досить продумані й що в ПЗ немає прихованих помилок. Такі помилки будуть, в остаточному підсумку, виявлятися користувачами й коректуватися розроблювачем на етапі супроводу (коли вартість виправлення зростає в 60-100 разів у порівнянні з етапом розробки).

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

Організація тестування

Тестування здійснюється на заданому заздалегідь безлічі вхідних даних X і безлічі передбачуваних результатів Y - (X,Y), які задають графік бажаної функції.

При покроковому виконанні програми код виконується рядок за рядком. Покрокове виконання дотепер є потужним методом автономного тестування й налагодження невеликих програм. Виконання із замовленими зупинками (breakpoints), аналізом трас (traces) або станів пам'яті - дампів (dump). Контрольна точка (breakpoint) - точка програми, що при її досягненні посилає відладнику сигнал. По цьому сигналі або тимчасово припиняється виконання програми, що налагоджується, або запускається програма "агент", що фіксує стан заздалегідь визначених змінних або областей у цей момент. Коли виконання в контрольній точці припиняється, програма, що налагоджується, переходить у режим останова (break mode). Вхід у режим останова не перериває й не закінчує виконання програми й дозволяє аналізувати стан окремих змінних або структур даних. Повернення з режиму break mode у режим виконання може відбутися в будь-який момент за бажанням користувача. Коли в контрольній точці викликається програма "агент", вона теж припиняє виконання програми, але тільки на час, необхідне для фіксації стану обраних змінних або структур даних у спеціальному електронному журналі - Log-файлі, після чого відбувається автоматичне повернення в режим виконання. Траса - це "збережений шлях " на керуючому графі програми, тобто зафіксовані в журналі записи про стани змінних у заданих точках у ході виконання програми.

Дамп - область пам'яті, стан якої фіксується в контрольній точці у вигляді єдиного масиву або декількох зв'язаних масивів. При аналізі, що здійснюється після виконання траси в режимі off-line, стану дампа структуруються, і виділені області або поля рівняються зі станами, передбаченими специфікацією. Наприклад, при моделюванні поводження керуючих програм контролерів у вигляді дампа фіксуються області загальних і спеціальних регістрів, або цілі області оперативної пам'яті, стану якої визначає алгоритм керування зовнішнім середовищем.

Зворотне виконання програми можливе за умови збереження на кожному кроці програми всіх значень змінних або станів програми для відповідної траси. Тоді піднімаючись від кінцевої точки траси до будь-який іншої, можна по кроках зробити обчислення станів, рухаючись від наслідку до причини, від станів на виході перетворювача даних до станів на його вході. Природно, такі можливості ми одержуємо в режимі off-line аналізу при фіксації в Log - файлі всієї історії виконання траси.

Отже, у процесі тестування порівняння проміжних результатів з отриманими незалежно еталонними результатами дозволяє знайти причини й місце помилки, виправити текст програми, провести повторну трансляцію й настроювання на виконання й продовжити тестування.

Тестування - це:

1) процес виконання ПЗ системи або компонента в умовах аналізу або запису одержуваних результатів з метою перевірки (оцінки) деяких властивостей об'єкту, що тестується.

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

3)контрольоване виконання програми на кінцевій безлічі тестових даних і аналіз результатів цього виконання для пошуку помилок.

Три фази тестування

1. Створення тестового набору (test suite) шляхом ручної розробки або автоматичної генерації для конкретного середовища тестування (testing environment).

2. Прогін програми на тестах, керований тестовим монітором (test monitor, test driver) з одержанням протоколу результатів тестування (test log).

3. Оцінка результатів виконання програми на наборі тестів з метою прийняття рішення про продовження або зупинку тестування.

Основна проблема тестування - визначення достатності безлічі тестів для істинності виводу про правильність реалізації програми, а також знаходження безлічі тестів, що володіє цією властивістю.

Тестування програми на всіх вхідних значеннях неможлива. Неможливе тестування й на всіх шляхах. Отже, треба відбирати кінцевий набір тестів, що дозволяє перевірити програму на основі наших інтуїтивних уявлень.

Завдання про вибір кінцевого набору тестів (X,Y) для перевірки програми в загальному випадку нерозв'язні. Тому для рішення практичних завдань залишається шукати окремі випадки рішення цього завдання.

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

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

Класи критеріїв

1. Структурні критерії використовують інформацію про структуру програми (критерії так званого "білого ящика")

2. Функціональні критерії формулюються в описі вимог до програмного виробу ( критерії так званого "чорного ящика" )

3. Критерії стохастичного тестування формулюються в термінах перевірки наявності заданих властивостей у додатка, що тестується. засобами перевірки деякої статистичної гіпотези.

4. Мутаційні критерії орієнтовані на перевірку властивостей програмного виробу на основі підходу Монте-Карло.

Лекція 2 (2 години)

Тема: Принципи тестування „чорного ” та „білого ” ящиків

Тестування «чорного ящика»

Відомі: функції програми.

Досліджується: робота кожної функції на всій області визначення.

Як показано на мал. 1.2, основне місце застосування тестів «чорного ящика» - інтерфейс ПЗ.

Мал. 1.2. Тестування «чорного ящика»

Ці тести демонструють:

- як виконуються функції програм;

- як приймаються вихідні дані;

- як виробляються результати;

- як зберігається цілісність зовнішньої інформації.

При тестуванні «чорного ящика» розглядаються системні характеристики програм, ігнорується їх внутрішня логічна структура. Вичерпне тестування, як правило, неможливо. Наприклад, якщо в програмі 10 вхідних величин і кожна приймає по 10 значень, то буде потрібно 1010 тестових варіантів. Відзначимо також, що тестування «чорного ящика» не реагує на багато особливостей програмних помилок.

Тестування «білого ящика»

Відома: внутрішня структура програми.

Досліджуються: внутрішні елементи програми й зв'язки між ними (мал. 1.3).

Мал. 1.3. Тестування «білого ящика»

Об'єктом тестування тут є не зовнішня, а внутрішня поведінка програми. Перевіряється коректність побудови всіх елементів програми й правильність їхньої взаємодії один з одним. Звичайно аналізуються керуючі зв'язки елементів, рідше - інформаційні зв'язки. Тестування за принципом «білого ящика» характеризується ступенем, у який тести виконують або покривають логіку (вихідний текст) програми. Вичерпне тестування також неможливе. Особливості цього принципу тестування розглянемо окремо.

Особливості тестування «білого ящика»

Звичайне тестування «білого ящика» засновано на аналізі керуючої структури програми. Програма вважається повністю перевіреної, якщо проведено вичерпне тестування маршрутів (шляхів) її графа керування.

У цьому випадку формуються тестові варіанти, у яких:

- гарантується перевірка всіх незалежних маршрутів програми;

- проходяться галузі True, False для всіх логічних рішень;

- виконуються всі цикли (у межах їхніх границь і діапазонів);

- аналізується правильність внутрішніх структур даних.

Класифікація структурних методів тестування

Модульне тестування - це тестування програми на рівні окремо взятих модулів, функцій або класів. Мета модульного тестування у виявленні локалізованих у модулі помилок у реалізації алгоритмів, а також у визначенні ступеня готовності системи до переходу на наступний рівень розробки й тестування. Модульне тестування проводиться за принципом "білого ящика", тобто ґрунтується на знанні внутрішньої структури програми, і часто включає ті або інші методи аналізу покриття коду.

Модульне тестування звичайно має на увазі створення навколо кожного модуля певного середовища, що включає заглушки для всіх інтерфейсів модуля, що тестується. Деякі з них можуть використовуватися для подачі вхідних значень, інші для аналізу результатів, присутність третіх може бути продиктована вимогами, що накладаються компілятором і збирачем.

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

Саме ефективність виявлення тих або інших типів дефектів повинна визначати стратегію модульного тестування, тобто розміщення акцентів при визначенні набору вхідних значень. В організації, що займається розробкою програмного забезпечення, як правило, є історична база даних ( Repository ) розробок, що зберігає конкретні відомості про розробку попередніх проектів: про версії й зборки коду ( build ) зафіксованих у процесі розробки продукту, про прийняті рішення, допущені прорахунки, помилки, успіхи і т.п. Провівши аналіз характеристик колишніх проектів, подібних замовленому організації, можна забезпечити нову розробку від старих помилок, наприклад, визначивши типи дефектів, пошук яких найбільш ефективний на різних етапах тестування.

У цьому випадку аналізується етап модульного тестування. Якщо аналіз не дав потрібної інформації, наприклад, у випадку проектів, у яких відповідні дані не збиралися, то основним правилом стає пошук локальних дефектів, у яких код, ресурси й інформація, залучені в дефект, характерні саме для даного модуля. У цьому випадку на модульному рівні помилки, зв'язані, наприклад, з невірним порядком або форматом параметрів модуля, можуть бути пропущені, оскільки вони втягують інформацію, що зачіпає інші модулі (а саме, специфікацію інтерфейсу), у той час як помилки в алгоритмі обробки параметрів досить легко виявляються.

Будучи по способу виконання структурним тестуванням або тестуванням "білого ящика", модульне тестування характеризується ступенем, у якому тести виконують або покривають логіку програми (вихідний текст). Тести, зв'язані зі структурним тестуванням, будуються по наступних принципах:

1. На основі аналізу потоку керування. У цьому випадку елементи, які повинні бути покриті при проходженні тестів, визначаються на основі структурних критеріїв тестування С0, С1,С2. До них ставляться вершини, дуги, шляхи керуючого графа програми (КГП), умови, комбінації умов і т.п.

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

Тестування на основі потоку керування. Особливості використання структурних критеріїв тестування С0,С1,С2 розглянуті в попередній лекції. До них варто додати критерій покриття умов, що полягає в покритті всіх логічних (булевских) умов у програмі. Критерії покриття рішень (галузей - С1) і умов не заміняють один одного, тому на практиці використовується комбінований критерій покриття умов/рішень, що сполучає вимоги по покриттю й рішень, і умов.

До популярних критеріїв відноситься критерій покриття функцій програми, відповідно до якого кожна функція програми повинна бути викликана хоча б один раз, і критерій покриття викликів, відповідно до якого кожний виклик кожної функції в програмі повинен бути здійснений хоча б один раз. Критерій покриття викликів відомий також як критерій покриття пар викликів (call pair coverage).

Тестування на основі потоку даних. Цей вид тестування спрямований на виявлення посилань на не ініціалізовані змінні й надлишкові присвоювання (аномалій потоку даних ). Запропонована стратегія вимагає тестування всіх взаємозв'язків, що включають у себе посилання (використання) і визначення змінної, на яку вказує посилання (тобто потрібне покриття дуг інформаційного графа програми). Недолік стратегії в тому, що вона не включає критерій С1, і не гарантує покриття рішень.

Стратегія необхідних пар також тестує згадані взаємозв'язки. Використання змінної в предикаті дублюється відповідно до числа виходів рішення, і кожна з таких необхідних взаємозв'язків повинна бути протестована. До популярних критеріїв належить критерій СР, що полягає в покритті всіх таких пар дуг v і w, що з дуги v досяжна дуга w, оскільки саме на дузі може відбутися втрата значення змінної, котра надалі вже не повинна використовуватися. Для "покриття" ще одного популярного критерію Cdu досить тестувати пари (вершина, дуга), оскільки визначення змінної відбувається у вершині КГП, а її використання - на дугах, що виходять із рішень, або в обчислювальних вершинах.

Лекція 3 (2 години)

Тема: Тестування базового шляху. Потоковий граф та цикломатична складність

Методи проектування тестових шляхів для досягнення заданого ступеня протестованості в структурному тестуванні. Процес побудови набору тестів при структурному тестуванні прийнято ділити на три фази:

1. Конструювання КГП.

2. Вибір тестових шляхів.

3. Генерація тестів, що відповідають тестовим шляхам.

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

На третій фазі по відомих шляхах тестування здійснюється пошук підходящих тестів, що реалізують проходження цих шляхів.

Друга фаза забезпечує вибір тестових шляхів. Виділяють три підходи до побудови тестових шляхів:

1. Статичні методи.

2. Динамічні методи.

3. Методи реалізованих шляхів.

Статичні методи. Найпростіше й легко реалізоване рішення - побудова кожного шляху за допомогою поступового його подовження за рахунок додавання дуг, поки не буде досягнута вихідна вершина керуючого графа програми. Ця ідея може бути посилена в так званих адаптивних методах, які щораз додають тільки один тестовий шлях (вхідний тест), використовуючи попередні шляхи (тести) як керівництво для вибору наступних шляхів відповідно до деякої стратегії. Найчастіше адаптивні стратегії застосовуються стосовно критерію С1. Основний недолік статичних методів полягає в тому, що не враховується можлива неможливість реалізації побудованих шляхів тестування. Достоїнство статичних методів в порівняно невеликій кількості необхідних ресурсів, як при використанні, так і при розробці. Однак їхня реалізація може містити непередбачений відсоток браку (нереалізованих шляхів). Крім того, у цих системах перехід від покриваючої безлічі шляхів до повної системи тестів користувач повинен здійснити вручну, а ця робота досить трудомістка.

Динамічні методи. Такі методи припускають побудова повної системи тестів, що задовольняють заданому критерію, шляхом одночасного рішення завдання побудови покриваючої безлічі шляхів і тестових даних. При цьому можна автоматично враховувати, реалізуються або не реалізуються, раніше розглянуті шляхи або їхні частини. Основною ідеєю динамічних методів є приєднання до початкових реалізованих відрізків шляхів подальших їхніх частин так, щоб: 1) не втрачати при цьому реалізованості знову отриманих шляхів; 2) покрити необхідні елементи структури програми. Динамічні методи вимагають значно більших ресурсів як при розробці, так і при експлуатації, однак збільшення витрат відбувається, в основному, за рахунок розробки й експлуатації апарата визначення реалізованості шляхів (символічний інтерпретатор, вирішувач нерівностей). Достоїнство цих методів полягає в тому, що їхня продукція має деякий якісний рівень - реалізованість шляхів.

Методи реалізованих шляхів. Дана методика полягає у виділенні з безлічі шляхів підмножини всіх реалізованих шляхів. Після чого покриваюча безліч шляхів будується з отриманої підмножини реалізованих шляхів. Методи реалізованих шляхів дають найкращий результат.

Тестування базового шляху — це спосіб, що заснований на принципі «білого ящика». Автор цього способу - Том Маккейб (1976).

Спосіб тестування базового шляху дає можливість:

- одержати оцінку комплексної складності програми;

- використати цю оцінку для визначення необхідної кількості тестових варіантів.

Тестові варіанти розробляються для перевірки базової множини шляхів (маршрутів) у програмі. Вони гарантують однократне виконання кожного оператора програми при тестуванні.

Для представлення програми використовується потоковий граф. Перелічимо його особливості.

1. Граф будується відображенням керуючої структури програми. У ході відображення закриваючі дужки умовних операторів і операторів циклів (end if; end loop) розглядаються як окремі (фіктивні) оператори.

2. Вузли (вершини) потокового графа відповідають лінійним ділянкам програми, включають один або декілька операторів програми.

3. Дуги потокового графа відображають потік керування в програмі (передачі керування між операторами). Дуга - це орієнтоване ребро.

4. Розрізняють операторні та предикатні вузли. З операторного вузла виходить одна дуга, а із предикатного - дві дуги.

Предикатні вузли відповідають простим умовам у програмі. Складена умова програми відображається в кілька предикатних вузлів. Складеною називають умову, в якій використовується одна або декілька бульових операцій (OR, AND).

Наприклад, фрагмент програми

if a OR b

then x

else в

end if;

можна відобразити у потоковий граф, представлений на мал. 1.4

Мал. 1.4 Перетворений потоковий граф

5. Замкнуті області, утворені дугами й вузлами, називають регіонами.

6. Навколишнє середовище графу розглядається як додатковий регіон. Наприклад, показаний тут граф має три регіони - Rl, R2, R3.

Приклад 1. Розглянемо процедуру стиску:

1 виконувати поки немає EOF

1 читати запис;

2 якщо запис порожній

3 те видалити запис:

4 інакше якщо поле а >= поля b

5 те видалити b;

6 інакше видалити а;

7а кінець якщо;

7а кінець якщо;

7b кінець виконувати;

8 кінець стиск;

Мал. 1.5. Перетворений потоковий граф процедури стиску

Вона відображається в потоковий граф, представлений на мал. 1.5. Бачимо, що цей потоковий граф має чотири регіони.

Цикломатична складність. Цикломатична складність - метрика ПЗ, що забезпечує кількісну оцінку логічної складності програми. У способі тестування базового шляху цикломатична складність визначає:

- кількість незалежних шляхів у базовій множині програми;

- верхню оцінку кількості тестів, що гарантує однократне виконання всіх операторів.

Незалежним називається будь-який шлях, що вводить новий оператор обробки або нову умову. У термінах потокового графа незалежний шлях повинен містити дугу, що не входить у раніше визначені шляхи. Шлях починається в початковому вузлі, а закінчується в кінцевому вузлі графа. Незалежні шляхи формуються в порядку від самого короткого до самого довгого.

Перелічимо незалежні шляхи для потокового графа із приклада 1:

Шлях 1: 1-8.

Шлях 2: 1-2-3-7а-7b-1-8.

Шлях 3: 1-2-4-5-7а-7b-1-8.

Шлях 4: 1-2-4-6-7а-7b-1-8.

Як видно з прикладу, кожний новий шлях включає нову дугу. Всі незалежні шляхи графа утворять базову множину. Властивості базової множини:

1) тести, що забезпечують його перевірку, гарантують:

- однократне виконання кожного оператора;

- виконання кожної умови по True-галузі й по False-галузі;

2) потужність базової множини дорівнює цикломатичній складності потокового графа.

Значення 2-гої властивості важко переоцінити - воно дає апріорну оцінку кількості незалежних шляхів, що має сенс шукати в графі.

Цикломатична складність обчислюється одним із трьох способів:

1) цикломатична складність дорівнює кількості регіонів потокового графа;

2) цикломатична складність визначається по формулі V(G)-E-N+2,

де Е — кількість дуг, N — кількість вузлів потокового графа;

3) цикломатична складність формується по вираженню V(G) =p+ 1, де р — кількість предикатних вузлів у потоковому графі G.

Обчислимо цикломатичну складність графа із приклада 1 кожним із трьох способів:

1) потоковий граф має 4 регіони;

2) V(G) = 11 дуг - 9 вузлів + 2 = 4;

3) V(G) = 3 предикатних вузли +1=4.

Таким чином, цикломатична складність потокового графа із приклада 1 дорівнює чотирьом.

Лекція 4 (2 години)

Тема: Способи тестування умов. Тестування галужень та операторів відношень

Способи тестування умов

Мета цього сімейства способів тестування - будувати тестові варіанти для перевірки логічних умов програми. При цьому бажано забезпечити охоплення операторів із всіх галузей програми.

Розглянемо термінологію, яка тут застосовується.

Проста умова - булева змінна або вираз відношення.

Вираз відношення має вигляд

Е1 <оператор відношення> E2,

де El, Е2 — арифметичні вирази, а в якості оператора відношенн використовується один з наступних операторів: <, >, =, , .

Складена умова складається з декількох простих умов, булевих операторів і круглих дужок. Будемо застосовувати бульові оператори OR, AND (&), NOT. Умови, що не містять виразів відношень, називають бульовими виразами.

Таким чином, елементами умови є: бульовий оператор, булева змінна, пара дужок (що містить просту або складену умову), оператор відношення, арифметичний вираз. Ці елементи визначають типи помилок в умовах.

Якщо умова некоректна, то некоректний, щонайменше, один з елементів умови. Отже, в умові можливі наступні типи помилок:

1. помилка булева оператора (наявність некоректних / відсутніх / надлишкових бульових операторів);

2. помилка бульової змінної;

3. помилка бульової дужки;

4. помилка оператора відношення;

5. помилка арифметичного виразу.

Спосіб тестування умов орієнтований на тестування кожної умови в програмі. Методики тестування умов мають два достоїнства. По-перше, досить просто виконати вимір тестового покриття умови. По-друге, тестове покриття умов у програмі - це фундамент для генерації додаткових тестів програми.

Метою тестування умов є визначення не тільки помилок в умовах, але й інших помилок у програмах. Якщо набір тестів для програми А ефективний для виявлення помилок в умовах, що містяться в А, то імовірно, що цей набір також ефективний для виявлення інших помилок в А. Крім того, якщо методика тестування ефективна для виявлення помилок в умові, то імовірно, що ця методика буде ефективна для виявлення помилок у програмі.

Існує кілька методик тестування умов.

Найпростіша методика — тестування галужень. Тут для складеної умови С перевіряється:

- кожна проста умова ( що входить у нього);

- Тruе-гілка;

- False-гілка.

Інша методика — тестування області визначення. У ній для виразу відношення потрібна генерація 3-4 тестів. Вираз виду

Е1 <оператор відношення > Е2

перевіряється трьома тестами, які формують значення Е1 більшим, ніж Е2, рівним Е2 і меншим, чим Е2.

Якщо оператор відношення невірний, а Е1 і Е2 коректні, то ці три тести гарантують виявлення помилки оператора відношень.

Для визначення помилок в Е1 і Е2 тест повинен сформувати значення Е1 більшим або меншим, чим Е2, причому забезпечити як можна меншу різницю між цими значеннями.

Для бульових виразів із n змінними потрібен набір з 2n тестів. Цей набір дозволяє виявити помилки бульових операторів, змінних і дужок, але практичний тільки при малому n. Втім, якщо в булевий вираз кожна бульова змінна входить тільки один раз, то кількість тестів легко зменшується.

Обговоримо спосіб тестування умов, що базується на наведених вище методиках.

Тестування галужень і операторів відношень

Спосіб тестування галужень і операторів відношень (автор К. Тай, 1989) виявляє помилки розгалуження й операторів відношень в умові, для якої виконуються наступні обмеження:

- всі бульові змінні й оператори відношень входять в умову тільки один раз;

- в умові немає загальних змінних.

У даному способі використовуються природні обмеження умов (обмеження на результат). Для складеної умови С, що включає n простих умов, формується обмеження умови:

ОУс = (d1,d2,d3.....dn),

де di — обмеження на результат i-ї простої умови.

Обмеження на результат фіксує можливі значення аргументу (змінної) простої умови (якщо він один) або співвідношення між значеннями аргументів (якщо їх мало).

Якщо i-та проста умова є бульовою змінною, то її обмеження на результат складається із двох значень і має вигляд

di = (true, false).

Якщо j-та проста умова є виразом відношення, то його обмеження на результат складається із трьох значень і має такий вигляд:

dj= (>,<,=).

Говорять, що обмеження умови ОУc (для умови С) покривається виконанням С, якщо в ході цього виконання результат кожної простої умови в С задовольняє відповідному обмеженню в ОУc.

На основі обмеження умови ОУ створюється обмежуюча множина ОМ, елементи якої є сполученнями всіх можливих значень d1, d2, d3, ..., dn.

Обмежуюча множина - зручний інструмент для запису завдання на тестування, адже вона складається з відомостей про значення змінних, які впливають на значення умови, що перевіряється. Пояснимо це на прикладі. Нехай треба перевірити умову, що складена із трьох простих умов:

b&(х>у)&а.

Умова приймає істинне значення, якщо всі прості умови істинні. У термінах значень простих умов це відповідає запису

(true, true, true),

а в термінах обмежень на значення аргументів простих умов - запису

(true, >, true).

Ясно, що другий запис є прямим керівництвом для написання тесту. Він вказує, що змінна b повинна мати істинне значення, значення змінної х повинне бути більше значення змінної в, і, нарешті, змінна а повинна мати істинне значення.

Отже, кожний елемент ОМ задає окремий тестовий варіант. Вихідні дані тестового варіанту повинні забезпечити відповідну комбінацію значень простих умов, а очікуваний результат дорівнює значенню складеної умови.

Розгляд прикладів

Приклад 1. Як приклад розглянемо дві типові складові умови:

С& = а & b, Сor =а or b,

де а й b — бульові змінні. Відповідні обмеження умов приймають вигляд:

ОУ&=( d1,d2), ОУor=( d1,d2),

де d1 = d2 = (true, false).

Обмежуючі множини зручно будувати за допомогою таблиці істинності (табл. 1.1).

Таблиця 1.1. Таблиця істинності логічних операцій

Варіант

а

b

a & b

a or b

1

false

false

false

false

2

false

true

false

true

3

true

false

false

true

4

true

true

true

true

Бачимо, що таблиця задає в ОМ чотири елементи (і відповідно, чотири тестових варіанти).

З погляду тестування, нам треба оцінювати вплив складеної умови на програму. Складена умова може приймати тільки два значення, але кожне зі значень залежить від великої кількості простих умов. Стоїть задача - позбутися від впливу надлишкових сполучень значень простих умов.

Скористаємося ідеєю скороченої схеми обчислення - елементи виразу обчислюються доти, поки вони впливають на значення виразу. При тестуванні необхідно виявити помилки перемикання, тобто помилки через бульовий оператор, оперуючи значеннями простих умов (бульових змінних). При такому інженерному підході справедливі наступні висновки:

- для умови типу І (а & b) варіанти 2 і 3 поглинають варіант 1. Тому обмежуюча множина має вигляд:

ОМ& = {(false, true), (true, false), (true, true)};

- для умови типу АБО (а or b) варіанти 2 і 3 поглинають варіант 4. Тому обмежуюча множина має вигляд:

ОМor = {(false, false), (false, true), (true, false)}.

Розглянемо кроки способу тестування галужень і операторів відношення.

Для кожної умови в програмі виконуються наступні дії:

1) будується обмеження умов ОУ;

2) виявляються обмеження результату по кожній простій умові;

3) будується обмежуюча множина ОМ. Побудова виконується шляхом підстановки в константні формули ОМ& або OMOR виявлених обмежень результату;

4) для кожного елемента ОМ розробляється тестовий варіант.

Приклад 2. Розглянемо складену умову С1 виду:

В1 &(E1,E2),

де В1 — бульовий вираз, E1, Е2 — арифметичні вирази.

Обмеження складеної умови має вигляд

ОУс1 =( d1,d2),

де обмеження простих умов рівні

d1 = (true, false), d2 = (=, <, >).

Проводячи аналогію між С1 і С& (різниця лише в тім, що в С1 друга проста умова — це вираз відношення), ми можемо побудувати обмежуючу множину для С1 з модифікацією

ОМ& = {(false, true), (true, false), (true, true)}.

Помітимо, що true для (E1= E2) означає =, a false для (E1 = E2) означає або <, або >. Заміняючи (true, true) і (false, true), обмеженнями (true, =) і (false, =) відповідно, a (true, false) — обмеженнями (true, <) і (true, >), одержуємо обмежуючу множину для С1:

ОМС1 = {(false,=),(true,<),(true,>),(true,=)}.

Покриття цієї множини гарантує виявлення помилок бульових операторів і операторів відношень в С1.

Лекція 5 (2 години)

Тема: Способи тестування циклів

Тестування циклів

Цикл - найпоширеніша конструкція алгоритмів, реалізованих у ПЗ. Тестування циклів виконується за принципом «білого ящика», при перевірці циклів основна увага звертається на правильність конструкцій циклів.

Розрізняють 4 типи циклів: прості, вкладені, об'єднані, неструктуровані. Структура циклів наведена на мал. 1.6

Мал. 1.6 Типові структури циклів

Прості цикли

Для перевірки простих циклів з кількістю повторень п може використатися один з наступних наборів тестів:

1) прогін усього циклу;

2) тільки один прохід циклу;

3) два проходи циклу;

4) т проходів циклу, де т<п;

5) п - 1, п, п + 1 проходів циклу.