Очевидно, що не всяка синтаксично правильна програма є коректною у вказаному вище значенні, т. е. коректність характеризує семантичні властивості програм.
5
З урахуванням специфіки появи помилок в програмах можна виділити дві сторони поняття коректності:
1) коректність як точна відповідність цілям розробки програми (які відображені в специфікації) при умові її завершення або часткова коректність;
2) завершення програми, тобто досягнення програмою в процесі її виконання своєї кінцевої точки.
У залежності від виконання або невиконання кожного з двох названих властивостей програми розрізнюють шість задач аналізу коректності:
1) доказ часткової коректності;
2) доказ часткової некоректність;
3) доказ завершення програми;
4) доказ незавершення програми;
5) доказ тотальної (повної ) коректності (тобто одночасне рішення першої і третьої задач);
6) доказ некоректність (рішення другої або четвертої задачі).
Методи доказу часткової коректності програм як правило спираються на аксіоматичний підхід до формалізації семантики мов програмування. У цей час відомі аксіоматичні семантики Паськаля, підмножини ПЛ/1 і деяких інших мов.
Аксіоматична семантика мови програмування являє собою сукупність аксіом і правил висновку. За допомогою аксіом задається семантика простих операторів мови (привласнення, введення - виведення, процедур). За допомогою правил висновку описується семантика складових операторів або керуючих структур (послідовності, умовного вибору, циклів). Серед цих правил висновку треба відмітити правило висновку для операторів циклу оскільки воно вимагає знання інваріанта циклу (формули, істинності якій не змінюється при будь-якому проходженні циклу).
Побудова інваріанта для оператора циклу по його тексту є алгоритмічно не вирішуваної задачі, тому для опису семантики циклів потрібно свого роду "підказка" від розробника програми.
Найбільш відомим з методів доказу часткової коректності програм є метод індуктивних тверджень запропонований Флойдом і вдосконалений Хоаром. Метод складається з трьох етапів.
Перший етап - отримання анотованої програми. На цьому етапі для синтаксично правильної програми повинні бути задані твердження на мові логіки предикатів першого порядку:
6
вхідний предикат;
вихідний предикат;
за одному твердженням для кожного циклу (ці твердження задаються для вхідної точки циклу і повинні характеризувати семантику обчислень в циклі).
Доказ неістинності умов коректності свідчить про неправильність програми, або її специфікації, або програми і специфікацій.
Незважаючи на достатню складність процесу верифікації програми і на те, що навіть успішно завершена верифікація не дає гарантій якості програми ( так як помилка може міститися і у верифікації ), застосування методів аналітичного доказу правильності дуже корисне для уточнення значення програми, що розробляється, а знання цих методів благотворно позначається на кваліфікації програміста.
Нарешті, динамічний контроль програми - це перевірка правильності програми при її виконанні на комп'ютері, тобто тестування.
ЦЕЛІ, ПРІНЦИПИ І ЕТАПИ ТЕСТУВАННЯ
Кожному програмісту відомо, скільки часу і сил йде на відладку і тестування програм. На цей етап доводиться біля 50% загальної вартості розробки програмного забезпечення.
Але не кожний з розробників програмних засобів може вірно визначити мету тестування. Нерідко можна почути, що тестування - це процес виконання програми з метою виявлення в ній помилок. Але ця мета недосяжна: ні яке саме ретельне тестування не дає гарантії, що програма не містить помилок.
Інше визначення тестування ( у м. Майерса ) тестування - це процес виконання програми з метою виявлення в ній помилок. Таке визначення мети стимулює пошук помилок в програмах. Звідси також ясно, що “вдалим" тестом є такою, на якому виконання програми завершилося з помилкою. Навпаки, “невдалим можна назвати тест, що не дозволив виявити помилку в програмі.
Визначення м. Маєрса вказує на об'єктивну трудність тестування: це деструктивний ( тобто зворотний творчому ) процес. Оскільки програмування - процес конструктивний, ясно, що більшості розробників програмних засобів складно “перемкнутися" при тестуванні створеної ними продукції.
7
У Майерса сформульовані також основні принципи організації тестування:
1) необхідною частиною кожного тесту повинно бути опис очікуваних результатів роботи програми, щоб можна було швидко з'ясувати наявність або відсутність помилки в ній;
2) слідує по можливості уникати тестування програми її автором, так як крім вже вказаної об'єктивної складності тестування для програмістів тут присутній і той чинник, що виявлення недоліків в своїй діяльності суперечить людській психології ( однак відладка програми ефективніше усього виконується саме автором програми );
3) по тих же міркуваннях організація - розробник програмного забезпечення не повинна “одноосібно " його тестувати ( повинні існувати організації, що спеціалізуються на тестуванні програмних засобів );
4) повинні бути правилом доскональне вивчення результатів кожного тесту, щоб не пропустити малопомітну на поверхневий погляд помилку в програмі;
5) необхідно ретельно підбирати тест не тільки для правильних ( передбачених ) вхідних даних, але і для неправильних (непередбачених);
6) при аналізі результатів кожного тесту необхідно перевіряти, чи не робить програма того, що вона не повинна робити;
7) потрібно зберігати використані тести (для підвищення ефективності повторного тестування програми після її модифікації або установки у замовника);
8) тестування не повинне плануватися виходячи з припущення, що в програмі не будуть виявлені помилки (зокрема, потрібно виділяти для тестування достатні тимчасові і матеріальні ресурси);
9) потрібно враховувати так званий “принцип скупчення помилок": імовірність наявності не виявлених помилок в деякій частині програми прямо пропорційна числу помилок, вже виявлених в цій частині;
10) потрібно завжди пам'ятати, що тестування - творчий процес, а не відноситися до нього як до рутинного заняття.
Існує два основних вигляду тестування: функціональне і структурне. При функціональному тестуванні програма розглядається як “чорний ящик" (тобто її текст не використовується). Відбувається перевірка відповідності поведінки програми її зовнішньої специфікації. Чи Можливо при цьому повне тестування програми? Очевидно, що критерієм повноти тестування в цьому випадку був би перебір всіх можливих значень вхідних даних, що нездійсненно.
8
Оскільки вичерпне функціональне тестування неможливе, мова може йти об розробки методів, що дозволяють підбирати тести не “наосліп", а з великою імовірністю виявлення помилок в програмі.
При структурному тестуванні програма розглядається як “білий ящик" (тобто її текст відкритий для користування ). Відбувається перевірка логіки програми. Повним тестуванням в цьому випадку буде таке, яке приведе до перебору всіх можливих шляхів на графі передач управління програми (її керуючому графові). Навіть для середніх по складності програм числом таких шляхів може досягати десятків тисяч. Якщо обмежитися перебором тільки лінійних не залежних шляхів, то і в цьому випадку вичерпне структурне тестування практично неможливе, т. к. неясне, як підбирати тести, щоб забезпечити “покриття" всіх таких шляхів. Тому при структурному тестуванні необхідно використати інші критерії його повноти, що дозволяють досить просто контролювати їх виконання, але не даючі гарантії повної перевірки логіки програми.