400 likes | 770 Views
Тестирование на основе моделей. к.ф.-м.н. В. В. Кулямин ИСП РАН. Тестирование вообще. Тестирование ( IEEE 610, SWEBOK ): Оценка соответствия системы требованиям к ней на основе результатов наблюдения за ее работой в специально подготовленных ситуациях
E N D
Тестирование на основе моделей к.ф.-м.н. В. В. КуляминИСП РАН
Тестирование вообще Тестирование (IEEE 610, SWEBOK): Оценка соответствия системы требованиям к ней на основе результатов наблюдения за ее работой в специально подготовленных ситуациях • Система в ходе тестирования должна работать • Нужно готовить специальные ситуации – тесты • Оценивается соответствие – ищем ошибки • Нужна общая оценка – ищем все ошибки
«Обычное» тестирование • Придумываем ситуацию • Оформляем ее в виде сценария взаимодействия теста с системой • Понимаем, как должна система вести себя в его рамках • Дополняем сценарий проверкой правильностиРезультат – тестовый вариант (test case) • Оцениваем достаточность имеющегося набора ситуаций: достаточно – конец, нет – goto 1
«Обычное» тестирование Ограниченная очередь размера 3 • В начале – пуста • put(X) • Y = take() • assert (Y == X) • В начале – полна • put(X) • assert (exception) ?
Зачем здесь модели? • Распознавание ошибки – ментальная модель правильной работы Math.abs(-2147483648) = • Полнота набора ситуаций – ментальная модель всех важных ситуаций При тестировании на основе моделей модели выделяются явно и заранее -2147483648
Используемые модели • Конечные автоматы(Finite State Machines, FSM) • Программные контракты(Software Contracts) • ...
Конечный автомат (банкомат) Время / Вывести исходное сообщение Начало Карта / Вывести приглашение ввести PIN Время / Вывести исходное сообщение Сообщение о выдаче баланса Сообщение о выдаче денег Сумма / Выдать деньги Сообщение о блокировке Запрос баланса / Выдать чек Выбор суммы Авторизация Некорректный PIN / Сообщение Выбор операции Корректный PIN / Вывести меню Авторизация 1 Запрос денег / Вывести вопрос о сумме Некорректный PIN / Заблокировать карту Некорректный PIN / Сообщение Авторизация 2
Тестирование на основе FSM 0 0 • Можно ли проверить, ведет ли себя неизвестная реализация всегда так же, как модель? • При каких условиях это можно сделать? a/x a/x b/y b/y b/y b/y a/x a/x 1 2 1 2 b/x b/x a/y a/y Модель Реализация
Проверка соответствия 0 b/y a/x • Требования к модели • Полная определенность • Минимальность • Сильная связность • Гипотезы о реализации • Реализация – конечный автомат с теми же стимулами и реакциями • Полная определенность • В начале находимся в начальном состоянии • Число состояний ограничено b/y a/x b/y 0 1 a/x b/y b/y a/x a/x a/y = 1 2 0 1 0 b/x a/y a/x b/y a, b 0 1 3 2 x, y
Методы проверки – обход 0 Построение обхода (transition tour) aababb s = status – возвращает идентификатор состояния sasasbsasbsbs 0x1x1x2y2y0y2 (xxxyyy) 0x1x1x2y2y1x2 (xxxyyx) 0x1x1x2y2y2y2 (xxxyyy) a/x b/y b/y a/x 1 2 b/x a/y 0 a/x b/y a/x 1 2 b/x a/y b/y 0 a/x b/y b/y a/x 1 2 b/x a/y
Методы проверки – W-метод 0 r= reset – переводит в начальное состояние S – множество последовательностей, достигающих всех состояний S = {ε, a, b} W – множество последовательностей, различающих все состояния W = {a, b} – 0:{x, y}; 1:{x, x}; 2:{y, y} S{a,b}W – полный тест {ε, a, b}{a, b}{a, b} = {aa, ab, ba, bb, aaa, aab, aba, abb, baa, bab, bba, bbb} aarabrbarbbraaaraabrabarabbrbaarbabrbbarbbb xx.xx.yy.yy.xxx.xxx.xxy.xxy.yyy.yyy.yyx.yyy xx.xx.yy.yy.xxx.xxx.xxy.xxy.yyy.yyy.yyy.yyy S{a,b}m-nW – полный тест для больших реализаций a/x b/y b/y a/x 1 2 b/x a/y reset 0 1 0 3 a/x b/y b/y 2 a/x 1 2 b/x a/y
Другие методы проверки • D-метод различающая последовательность u = ba – 0:yy; 1:xy; 2:yx S{a,b}u abarbbaraabarabbarbabarbbba • Методы, работающие без reset • Адаптивные методы 0 a/x b/y b/y a/x 1 2 b/x a/y
Получаемые тесты • abarbbaraabarabbarbabarbbba xxy.yyx.xxxy.xxyx.yyyx.yyyy • z = a(); assert(z == ‘x’);z = b(); assert(z == ‘x’);z= a(); assert(z == ‘y’); reset();… • Тесты теперь можно генерировать полностью автоматически, если выполнены все ограничения на модель
Конечные автоматы – еще не все • Не всякую задачу удобно описывать конечным автоматом • Часто можно только очень большим Сложность построения тестов O(p(m-n+1)n3) • Чаще всего ограничения на число состояний в реализации неизвестны • Часто требования недетерминированы • Часто результат в некотором состоянии определен не для всех стимулов
Конечные автоматы – еще не все Ограниченная очередь размера 3 [X, X, X] [X, X, Y] [X, X] [Y, X, X] [X] [X, Y] [X, Y, X] [Y, X, Y] [Y, X] [Y] [X, Y, Y] [Y, Y] [Y, Y, X] [Y, Y, Y]
Конечные автоматы – еще не все Система управления памятью void* malloc(int n) void free(void* m) malloc(7); malloc(3); malloc(5); malloc(4); malloc(7);
Конечные автоматы – еще не все Таймер выключить включить сигнал сигнал сигнал init(3) Барьер wait() wait() wait() Высота 3
Программные контракты • Система – набор взаимодействующих компонентов • Компоненты взаимодействуют с помощью вызовов интерфейсных операций друг друга • Каждая операция имеет • ПредусловиеОпределяет, когда операцию можно вызывать • ПостусловиеОписывает результаты работы операции
Пример контракта Вычисление целочисленного логарифма int logn(int x, int b) pre (b > 1) & (x > 0) post blogn≤ x & blogn+1 > x
Что это дает для тестирования? • Можно тестировать • отдельные компоненты • большие подсистемы • систему в целом • Постусловие дает критерий правильности • Тест можно разбить на два компонента • Генератор тестовых данных • Оракул – проверяет правильность работы на любых данных • Можно записывать сложные и недетерминированные ограничения
Более сложный пример АРМ компоновщика заказов • Показывает список заказов для обработки • Позволяет • Добавить новый заказ в конец списка • Добавить срочный заказ в конец подсписка срочных заказов • Пометить заказ как срочный • Убрать первый заказ из списка (когда он обработан)
Контракт добавления заказов List urgent; List ordinary; int MAX; boolean addOrdinary(Order o) { pre { returntrue; } post { if(@ordinary.size + @urgent.size < MAX) return ordinary == @( ordinary.add(o) ) && urgent == @urgent && addOrdinary == true ; else return ordinary == @ordinary && urgent == @urgent && addOrdinary == false ; } }
Контракт переноса заказа в срочные boolean moveToUrgent(Order o) { pre { returntrue; } post { if(@( o in ordinary )) return ordinary == @( ordinary.remove(o) ) && urgent == @( urgent.add(o) ) && moveToUrgent == true ; else return ordinary == @ordinary && urgent == @urgent && moveToUrgent == false ; } }
Контракт удаления заказа Order removeFirst() { pre { return urgent.size != 0 || ordinary.size != 0 ; } post { if(urgent.size != 0) return ordinary == @ordinary && urgent == @( urgent.removeFirst() ) && removeFirst == @( urgent[0] ) ; else return ordinary == @( ordinary.removeFirst() ) && urgent == @urgent && removeFirst == @( ordinary[0] ) ; } }
Что получилось? true / false true / false Оракул Тестируемая система Модель
Что еще надо? + • Проверка правильности • Построение тестовых данных • Оценка полноты набора тестов ? ?
Полнота тестов • Покрытие кода тестируемых функций • Метод функциональных диаграмм
Покрытие постусловия post { if ( a <= 0 || c.isActive() ) … else if( a > 3 & !b.closed() ) … else … } a > 0 && !c.isActive() && a <= 3 || a > 0 && !c.isActive() && b.closed()
Покрытия контракта и кода Постусловие Код • Если покрытие постусловия выше, то покрытие кода выше • 100% постусловия и 100% кода не следуют друг из друга
Метод функциональных диаграмм +: int × int → int int = {positive, 0, negative}
Метод функциональных диаграмм if(a > 0 && F(b) < 5) return f == g(a)-F(b)*b && a ==@a + 1; else if(isActive(c)) return f ==-1 && a ==@a; else return f == 0 && a ==@a; a > 0 f == g(a)-F(b)*b a == @a + 1 F(b) < 5 f == -1 isActive(c) a == @a f == 0
Пример – ветви постусловий • addOrdinary() • ordinary.size + urgent.size < MAX • ordinary.size + urgent.size == MAX • addUrgent() • ordinary.size + urgent.size < MAX • ordinary.size + urgent.size == MAX • moveToUrgent(o) • ( o in ordinary ) • !( o in ordinary ) • removeFirst () • urgent.size != 0 • ordinary.size != 0 adOrN adOrE adUrN adUrE mvN mvE rmUr rmOr
Обобщение состояний, шаг 2 urgent.size addOrN MAX addUrN addOrE, addUrE mvN mvE rmUr 0 rmOr ordinary.size 0 MAX
Итоги • Программные контракты • Оракул • Ветви постусловий – важные ситуации • Построить обход переходов обобщенного автомата • Подготовить тестовые данные (?)
В чем цель тестирования? • (Дейкстра)Тестирование не может подтвердить правильность, но может найти ошибки • => (?)Цель тестирования – поиск ошибок • <=Тестирование, не находящее ошибок – бесполезно
В чем цель тестирования? • А как бы мы иначе узнали, что ошибок в программе нет? • Тестирование – это метод оценки качества системы • Если ошибки есть, оно их должно находить • Если их нет, оно должно это подтверждать • Оно должно давать еще много информации • Какие части системы наиболее устойчивы • Где, вероятно, еще есть ошибки и какого рода • Достаточно ли высоко качество системы в целом и стоит ли тратить усилия на доработку • Модели – способ сделать эту оценку более надежной и объективной