Чи є формалізовані / математичні теорії тестування програмного забезпечення?


12

"Теорія тестування програмного забезпечення" Google, лише здається, дає теорії в м'якому сенсі цього слова; Мені не вдалося знайти нічого, що б класифікувалося як теорія в сенсі математичної, інформаційної теоретичної чи іншої наукової галузі.

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

ОНОВЛЕННЯ: Крім того, я не впевнений в інтуїтивному розумінні зв'язку між офіційною верифікацією та тим, що я запитав, але явно є певний зв’язок.


1
Тестування програмного забезпечення є дуже цінним (наприклад, впровадження одиничного тестування на практиці), але його теорія завжди матиме дірки. Розглянемо цей класичний приклад: double pihole(double value) { return (value - Math.PI) / (value - Math.PI); }що я дізнався у свого вчителя математики . У цьому коді є рівно одне отвір , яке неможливо виявити автоматично лише за допомогою тестування в чорному ящику. У Математиці немає такої діри. У підрахунку ви можете закрити отвір, якщо однобічні межі рівні.
rwong

4
Це може бути частиною того, що ви шукаєте - en.wikipedia.org/wiki/Formal_verification
enderland

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

З тих пір я ознайомився з країною формальної перевірки через залежні типи, і я можу повністю погодитися з @Doval та enderland.
Ерік Каплун

1
@rwong Думаю, ви натякаєте на те, що чисельник і знаменник можуть дорівнювати нулю. Частково проблема пов’язана з поганою конструкцією цієї функції. Якщо говорити про математичну формальну перевірку, вам потрібно складати свої функції не довільно, а слідуючи формальним правилам на основі правильних типів даних. У цьому прикладі вам потрібно буде використовувати функцію поділу (a,b)=>a/b, яку потрібно розширити значенням переповнення, щоб бути правильно складеним.
Дмитро Зайцев

Відповіді:


8

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

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


5

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

Режими тестування

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

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

Тест може лише довести наявність помилки, ніколи відсутність усіх помилок. Тести ставлять верхню межу правильності програми.

Кодове покриття

Для визначення метрики покриття коду вихідний код можна перевести на графік потоку управління, де кожен вузол містить лінійний сегмент коду. Контроль протікає між цими вузлами лише в кінці кожного блоку і завжди є умовним (якщо умова, то goto вузол A, інакше goto вузол B). Графік має один початковий вузол і один кінцевий вузол.

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

Тому часто корисно перевіряти стан покриття .

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

При побудові тестового входу з використанням покриття стану, тоді слід враховувати коротке замикання. Наприклад,

function foo(A, B) {
  if (A && B) x()
  else        y()
}

потребує тестування з foo(false, whatever), foo(true, false)та foo(true, true)для повного мінімального множинного покриття умов.

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

Існує кілька більш складних показників покриття, але вони, як правило, схожі на показники, представлені тут.

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

Функціональні тести

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

Слід додатково протестувати

  • крайні випадки length(""), foo("x"), length(longer_than_INT_MAX),
  • значення, дозволені мовою, але не контрактом функції length(null), і
  • можливі непотрібні дані length("null byte in \x00 the middle")

Що стосується числових даних, це означає тестування 0, ±1, ±x, MAX, MIN, ±∞, NaN, а порівняння з плаваючою комою - тестування двох сусідніх плавців. Як ще одне доповнення, з класів еквівалентності можна обрати випадкові значення тесту. Щоб полегшити налагодження, варто записати використане насіння…

Нефункціональні тести: Навантажувальні тести, Стресові тести

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

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

Нетестуючі методи

Відгуки

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

Коли огляди коду такі чудові, чому ми все ще пишемо тести? Великою перевагою тестових наборів є те, що вони можуть працювати (в основному) автоматично, і як такі дуже корисні для регресійних тестів .

Офіційна перевірка

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

Деякі інваріанти можна явно перевірити, використовуючи assertоператори.


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

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


2
Я ціную складний відповідь, але я боюся , що це не має майже нічого спільного з тим, що я запитав :) Але, на щастя, programmers.stackexchange.com/questions/78675 / ... , здається, так близько , як він отримує те , що я був націлений на.
Ерік Каплун

Це чудові речі. Чи можете ви порекомендувати будь-які книги чи речі?
Марцін

4

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

Тест :: Лектротест

Як каже автор, цей модуль Perl був натхненний модулем швидкої перевірки Haskell . На цій сторінці є більше посилань, деякі з яких є мертвими.


2

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

Система AETG: підхід до тестування на основі комбінаторної конструкції

(є ще багато таких посилань)


2

Використовуються деякі математичні рівняння, але це залежить від типу тестування програмного забезпечення, яке ви використовуєте. Наприклад, припущення про критичну помилку припускає, що відмови навряд чи є результатом двох або більше одночасних помилок. Наступне рівняння: f = 4n + 1. f = функція, яка обчислює кількість тестових випадків для заданої кількості змінних ( n) + 1 - це додавання постійної, де всі змінні приймають номінальне значення.

Інший тип тестування , який вимагає математичних рівнянь є грубості Тестування тестує надійність, або правильність тестів в процесі тестування. У цьому тесті слід вводити змінні в межах законного вхідного діапазону (чисті тестові випадки) та вхідні змінні за межами вхідного діапазону (брудні тестові випадки). Ви б використали наступне математичне рівняння: f = 6n + 1 . 6n вказує, що кожна змінна повинна приймати 6 різних значень, тоді як інші значення припускають номінальне значення. * + 1 * являє собою додавання постійної 1.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.