Тема. Критерії
вибору тестів
План
1.
Вимоги до
ідеального критерію тестування.
2.
Структурні
критерії (клас I).
3.
Функціональні
критерії (клас II).
4.
Стохастичні
критерії (клас III).
5.
Мутаційний
критерій (клас IV).
1.
Вимоги до ідеального критерію тестування
Вимоги до ідеального критерію можна
сформулювати наступним чином:
v Критерій повинен бути достатнім, тобто показувати, коли деяка кінцева кількість тестів достатня для тестування даної
програми.
v
Критерій
повинен бути повним, тобто у
випадку помилки повинен існувати тест, що задовольняє критерію, який розкриває помилку.
v Критерій повинен бути надійним, тобто будь-які дві умови із безліч тестів, що задовольняють йому, одночасно повинні розкривати або
не розкривати помилки програми.
v Критерій повинен легко перевірятися.
Для нетривіальних класів програм у загальному
випадку не існує повного й надійного критерію, що залежить від програм або
специфікацій.
Тому ми прагнемо до ідеального загального
критерію через реальні складові.
Класи критеріїв
ü
Структурні
критерії використають
інформацію про структуру програми (критерії так званого "білого
ящика").
ü
Функціональні
критерії формулюються
в описі вимог до програмного виробу ( критерії так називаного "чорного
ящика" ).
ü
Критерії
стохастичного тестування формулюються в термінах перевірки наявності заданих властивостей у
теститованого додатка, засобами перевірки деякої статистичної гіпотези.
ü
Мутаційні
критерії орієнтовані
на перевірку властивостей програмного виробу на основі підходу Монте-Карло.
2.
Структурні критерії (клас I)
Структурні критерії використовують модель
програми у вигляді "білого ящика", що припускає знання вихідного
тексту програми або специфікації програми у вигляді потокового графу керування. Структурна інформація зрозуміла й
доступна розроблювачам підсистем і модулів додатка, тому даний клас критеріїв
часто використається на етапах модульного й інтеграційного тестування (Unit
testing, Integration testing).
Структурні критерії базуються на основних
елементах КГП, операторах, гілках і шляхах.
Умова критерію тестування команд (критерій
С0) — набір тестів у сукупності повинен забезпечити проходження кожної команди
не менш одного разу. Це слабкий критерій, він, як правило, використається в
великих програмних системах, де інші критерії застосувати неможливо.
Умова критерію тестування гілок (критерій
С1) — набір тестів у сукупності повинен забезпечити проходження кожної гілки не
менш одного разу. Це досить сильний і при цьому економічний критерій, оскільки
безліч гілок у тестованому додатку зазвичай не така вже і велика. Даний
критерій часто використається в системах автоматизації тестування.
Умова критерію тестування шляхів (критерій
С2) — набір тестів у сукупності повинен забезпечити проходження кожного шляху
не менш 1 разу. Якщо програма містить цикл (особливо з неявно заданим числом
ітерацій), то число ітерацій обмежується константою (часто — 2, або числом
класів вихідних шляхів).
У прикладі 9
наведений зразок простої програми. Розглянемо умови її тестування у відповідно
void
Method (int x)
{
if
(x>17)
x = 17—x;
if (x==—13)
x = 0;
}
Приклад 9. Простої програми, для тестування за
структурними критеріями
Тестовий набір з одного тесту, задовольняє
критерію команд (C0):
(X, Y)={(xвх=30, xвих=0)}
покривають всі оператори траси 1—2—3—4—5—6
Тестовий набір із двох тестів, задовольняє
критерію гілок (C1):
(X, Y)={(30,0), (17, 17)} додає 1 тест до
безлічі тестів для С0 і трасу 1—2—4—6. Траса 1—2—3—4—5—6 проходить через всі
гілки досяжні в операторах if за умови true, а траса 1—2—4—6 через всі галузі,
досяжні в операторах if за умови false.
Тестовий набір із чотирьох тестів,
задовольняє критерію шляхів (C2):
(X,Y)={(30,0), (17,17), (—13,0), (21,—4)}
Набір умов для двох операторів if c мітками 2
й 4 наведений у таблиця 2
Таблиця 2 Умови операторів if |
||||
|
(30,0) |
(17,17) |
(—13,0) |
(21,—4) |
2 if (x>17) |
> |
|
≤ |
> |
4 if (x==—13) |
≠ |
≠ |
= |
≠ |
Критерій шляхів С2 перевіряє програму більш
ретельно, ніж критерії — C1, однак навіть якщо він задовільний, немає підстав
затверджувати, що програма реалізована у відповідності зі специфікацією.
Структурні критерії не перевіряють
відповідність специфікації, якщо вона не відбита в структурі програми. Тому при
успішному тестуванні програми за критерієм C2 ми можемо не помітити помилку,
пов’язану з невиконанням деяких умов специфікації вимог.
3.
Функціональні критерії (клас II)
Функціональний критерій — найважливіший для програмної індустрії
критерій тестування. Він забезпечує контроль ступеня виконання вимог замовника
в програмному продукті. Оскільки вимоги формулюються до продукту в цілому, вони
відбивають взаємодію тестованого додатка з оточенням. При функціональному
тестуванні переважно використовується модель "чорного ящика". Проблема
функціонального тестування — це, насамперед, трудомісткість; справа в тому, що
документи, які фіксують вимоги до програмного виробу
(Software requirement specification, Functional specification і т.п.), як
правило, досить об’ємні, але тим не менш, перевірка повинна бути ретельною.
Нижче наведені часткові види функціональних критеріїв.
v Тестування пунктів специфікації — набір тестів у сукупності повинен
забезпечити перевірку кожного тестованого пункту не менш одного разу.
v Специфікація вимог — може містити сотні й тисячі пунктів вимог до
програмного продукту й кожна із цих вимог під час тестування повинна бути перевірена відповідно до
критерію не менш чим одним тестом.
v Тестування класів вхідних даних — набір тестів у сукупності повинен
забезпечити перевірку представника кожного класу вхідних даних не менш одного
разу. При створенні тестів класи вхідних даних
зіставляються з режимами використання тестованого компонента або підсистеми додатка, що помітно скорочує
варіанти перебору, що враховують під час розробки тестових наборів. Варто помітити, що
перебираючи відповідно до критерію величини вхідних змінних (наприклад, різні
файли — джерела вхідних даних), ми змушені застосовувати потужні тестові
набори. Дійсно, поряд з обмеженнями на величини вхідних даних, існують
обмеження на величини вхідних даних у всіляких комбінаціях, у тому числі
перевірка реакцій системи на появу помилок у значеннях або структурах вхідних
даних. Облік цього різноманіття — процес трудомісткий, що створює складності
для застосування критерію.
v Тестування правил — набір тестів у сукупності повинен
забезпечити перевірку кожного правила, якщо вхідні й вихідні значення
описуються набором правил деякої граматики. Варто
помітити, що граматика повинна бути досить простою, щоб трудомісткість розробки
відповідного набору тестів була реальною (вписувалася в термін й штат фахівців,
виділених для реалізації фази тестування).
v Тестування класів вихідних даних — набір тестів у сукупності повинен
забезпечити перевірку представника кожного вихідного класу, за умови, що
вихідні результати заздалегідь не класифіковані, причому окремі класи
результатів ураховують, у тому числі, обмеження на ресурси або на час (time out). Під час створення
тестів класи вихідних даних зіставляються з режимами використання тестованого
компонента або підсистеми, що помітно скорочує варіанти перебору, які
враховують під час розробки тестових наборів.
v Тестування функцій — набір тестів у сукупності повинен
забезпечити перевірку кожної дії, реалізованої тестованим модулем, не менш
одного разу.
Дуже популярний на практиці критерій, що,
однак, не забезпечує покриття частини функціональності тестованого компонента,
зв’язаної зі структурними й поведінковими властивостями, опис яких не
зосереджено в окремих функціях (тобто опис зосереджений за компонентом).
Критерій тестування функцій поєднує часткові
особливості структурних і функціональних критеріїв. Він базується на моделі
"напівпрозорого ящика", де явно зазначені не тільки входи й виходи
тестованого компонента, але також склад і структура використовуваних методів
(функцій, процедур) і класів.
v Комбіновані критерії для програм і
специфікацій — набір тестів у сукупності повинен забезпечити перевірку всіх
комбінацій несуперечливих умов програм і специфікацій не менш одного разу. При цьому всі комбінації несуперечливих умов
треба підтвердити, а умови протиріч варто виявити й ліквідувати.
4.
Стохастичні критерії (клас III)
Стохастичне тестування застосовується під час тестування складних програмних комплексів — коли набір
детермінованих тестів (X, Y) має величезну потужність. У випадках, коли
подібний набір неможливо розробити й виконати на фазі тестування, можна
застосувати наступну методику.
ü
Розробити програми
— імітатори випадкових послідовностей вхідних сигналів {x}.
ü
Обчислити
незалежним способом значення {y} для відповідних вхідних сигналів {x} й
одержати тестовий набір (X, Y).
ü
Протестувати
додаток на тестовому наборі (X, Y),
використовуючи два способи контролю результатів:
Детермінований контроль — перевірка відповідності обчисленого
значення значенню y, отриманому в результаті прогону
тесту на наборі {x} — випадкової послідовності вхідних сигналів, що згенеровані
імітатором.
Стохастичний контроль — перевірка відповідності безлічі значень
{yв}, отриманого в результаті прогону тестів на наборі вхідних значень {x},
заздалегідь відомому розподілу результатів F(Y).
У цьому випадку безліч Y невідома (її
обчислення неможливе), але відомий закон розподілу даної безлічі.
Критерії стохастичного тестування
ü
Cтатичні методи закінчення тестування — стохастичні методи
прийняття рішень про збіг гіпотез про розподіл випадкових величин. До них
належать широко відомі: метод Стьюдента ( St ), метод Хі—квадрат ( )
і т.п.
ü
Метод оцінки швидкості виявлення помилок — заснований на моделі швидкості виявлення
помилок, відповідно до якої тестування припиняється, якщо оцінений інтервал
часу між поточною помилкою й наступної занадто великий для фази тестування
додатка.
Мал. 7. Залежність швидкості виявлення помилок від
часу виявлення
При формалізації моделі швидкості виявлення
помилок (мал.7) використалися наступні позначення:
N — вихідне число помилок у програмному
комплексі перед тестуванням,
C — константа зниження швидкості виявлення
помилок за рахунок знаходження чергової помилки.
t1, t2,... tn — кортеж зростаючих інтервалів виявлення
послідовності з n помилок,
T — час виявлення n помилок.
Якщо допустити, що за час T виявлено n
помилок, то справедливо співвідношення (1), яке стверджує, що добуток швидкості
виявлення i помилки й часу виявлення i помилки є 1 за визначенням:
(N – i + 1) * C * ti = 1 (1)
У цьому припущенні справедливе співвідношення
(2) для n помилок:
N*C*t1 + (N —
1) * C * t2 + … (N – n + 1) * c * tn = n (2)
N * C * (t1 +
t2 + … + tn) – C * Σ(i—1)ti = n
NCT – C * Σ(i — 1)ti
= n
Якщо з (1) визначити ti і просумувати від 1 до n, то прийдемо до співвідношення (3) для часу T виявлення n помилок:
Σ1 / (N – i + 1) =
TC (3)
Якщо з (2) виразити C, приходимо до
співвідношення (4):
C = n / (NT — Σ(i — 1)ti) (4)
Нарешті, підставляючи C в (3), одержуємо
остаточне співвідношення (5), зручне для оцінок:
Σ1 / (N – i + 1) = n / (N – 1/T * Σ(i
— 1)ti)) (5)
Якщо оцінити величину N приблизно, використовуючи відомі методи оцінки числа помилок у програмі або дані про щільність помилок для проектів розглянутого класу з історичної бази даних проектів, і, крім того, використати поточні дані про інтервали між помилками t1, t2 ... tn, отримані на фазі тестування, тj, підставляючи ці дані в (5), можна одержати оцінку tn+1 – тимчасового інтервалу необхідного для знаходження й виправлення чергової помилки (майбутньої помилки).
Якщо tn+1>Td —
припустимого часу тестування проекту, то тестування закінчуємо, у противному
випадку продовжуємо пошук помилок.
Спостерігаючи послідовність інтервалів
помилок t1, t2 … tn, і час, витрачений на
виявлення n помилок T = Σ ti, можна
прогнозувати інтервал часу до наступної помилки й уточнювати відповідно до (4) величину C.
5.
Мутаційний критерій (клас IV)
Вважається, що професійні програмісти пишуть
відразу майже правильні програми, що відрізняються від правильних дрібними
помилками або описками типу — перестановка місцями максимальних значень
індексів в описі масивів, помилки в знаках арифметичних операцій, заниження або
завищення границі циклу на 1 і т.п. Пропонується підхід, що дозволяє на основі
дрібних помилок оцінити загальне число помилок, що залишилися в програмі.
Підхід базується на наступних поняттях:
Мутації — дрібні помилки в програмі.
Мутанти — програми, що відрізняються один від одного мутаціями.
Метод мутаційного тестування — у розроблювальну програму P вносять
мутації, тобто штучно створюють програми—мутанти P1, P2... Потім
програма P і її мутанти тестуються на тому самому наборі тестів (X, Y).
Якщо на наборі (X, Y) підтверджується
правильність програми P й, крім того, виявляються всі внесені в
програми—мутанти помилки, то набір тестів (X, Y) відповідає мутаційному
критерію, а тестована програма оголошується правильною.
Якщо деякі мутанти невиявили всіх мутацій, то
треба розширювати набір тестів (X, Y) і продовжувати тестування.
Приклад застосування мутаційного критерію
Тестована програма P наведена в прикладі 10. Для неї створюється дві програми—мутанта P1
й P2.
В P1 змінене початкове значення змінної z з 1
на 2 ( приклад 10.1).
В P2 змінене початкове значення змінної i з 1
на 0 і граничне значення індексу циклу з n на n—1 (приклад 10.2).
При запуску тестів (X, Y) = {(x=2, n=3,
y=8),(x=999, n=1, y=999), (x=0, n=100, y=0)} виявляються всі помилки в
програмах—мутантах і помилка в основній програмі, де в умові циклу замість n стоїть n—1:
//
Метод обчислює негативну ступінь
n числа x
double PowerNonNeg(double x, int n)
{
double z=1;
int i;
if (n>0)
{
for (i=1;n—1>=i;i++)
{
z = z*x;
}
}
else printf("Помилка ! Ступінь числа n має бути більше 0.\n");
return z;
}
Приклад 10. Основна програма P
Змінене початкове значення змінної z у
мутанті Р1 ( z = 2 ):
//
Метод обчислює негативну ступінь n числа x
double PowerMutant1(double x, int n)
{
double z=2;
int i;
if (n>0)
{
for (i=1;n>=i;i++)
{
z = z*x;
}
}
else printf("Помилка ! Ступінь числа n має бути більше 0.\n");
return z;
}
Приклад 10.1. Програма мутант P1
Змінене початкове значення змінної i і
границі циклу в мутанті P2 ( i = 0; n — 1 ):
//
Метод обчислює негативну ступінь
n числа x
double PowerMutant2(double x, int n)
{
double z=1;
int i;
if (n>0)
{
for (i=0;n—1>=i;i++)
{
z = z*x;
}
}
else printf("Помилка ! Ступінь числа n має бути більше 0.\n");
return z;
}
Приклад 10.2.
Програма-мутант P2
Питання для самоконтролю:
1.
Які
вимоги можна сформулювати до ідеального критерію?
2.
Які класи
критеріїв можна виділити?
3.
Охарактеризуйте
Структурні критерії.
4.
Охарактеризуйте
Функціональні критерії.
5.
Охарактеризуйте
Критерії стохастичного тестування.
6.
Охарактеризуйте
функціональний критерій Тестування пунктів специфікації.
7.
Охарактеризуйте
функціональний критерій Тестування класів вхідних даних.
8.
Охарактеризуйте
функціональний критерій Тестування правил.
9.
Дайте
визначення стохастичних критеріїв.
10.
Що таке
Детермінований контроль тестування?
11.
Що таке
Стохастичний контроль тестування?
12.
Опишіть
метод мутаційних критеріїв.
13.
Що таке
мутація, що таке программа-мутант?