Tестирование программного обеспечения
Что, зачем и почему?
Software Testing 101
Марат Ахин
Санкт-Петербургский политехнический университет
2016
Марат Ахин (СПбПУ) Intro 2016 1 / 359
Содержание
1 Прелюдия
Обеспечение качества ПО
Тестирование ПО
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
6 Разработка через тестирование
7 Интеграционное тестирование
Марат Ахин (СПбПУ) Intro 2016 2 / 359
Обеспечение качества ПО
Функциональные vs нефункциональные требования
Марат Ахин (СПбПУ) Intro 2016 3 / 359
Обеспечение качества ПО
Функциональные требования
Адекватность
Точность
Интероперабельность
Безопасность
Нефункциональные требования
Надежность
Эффективность
Поддерживаемость
Переносимость
Как можно их проверять?
Марат Ахин (СПбПУ) Intro 2016 4 / 359
Обеспечение качества ПО
Марат Ахин (СПбПУ) Intro 2016 5 / 359
Обеспечение качества ПО
Thinking is hard, running is simple. (c)
Запустить программу просто и это можно сделать всегда
Думать о программе сложно и требует «высшего знания»
Будем запускать программу, чтобы проверить, отвечает ли она
предъявленным требованиям
Марат Ахин (СПбПУ) Intro 2016 6 / 359
Что такое тестирование ПО?
То, чем вы будете заниматься до 80% времени
Марат Ахин (СПбПУ) Intro 2016 7 / 359
Что за вопрос лежит в основе тестирования?
Работает ли это ПО правильно?
НЕТ
Работает ли это ПО неправильно?
ДА
Тестирование
=
Разрушение
Марат Ахин (СПбПУ) Intro 2016 8 / 359
Что за вопрос лежит в основе тестирования?
Работает ли это ПО правильно?
НЕТ
Работает ли это ПО неправильно?
ДА
Тестирование
=
Разрушение
Марат Ахин (СПбПУ) Intro 2016 8 / 359
Что за вопрос лежит в основе тестирования?
Работает ли это ПО правильно?
НЕТ
Работает ли это ПО неправильно?
ДА
Тестирование
=
Разрушение
Марат Ахин (СПбПУ) Intro 2016 8 / 359
Что за вопрос лежит в основе тестирования?
Работает ли это ПО правильно?
НЕТ
Работает ли это ПО неправильно?
ДА
Тестирование
=
Разрушение
Марат Ахин (СПбПУ) Intro 2016 8 / 359
Что за вопрос лежит в основе тестирования?
Работает ли это ПО правильно?
НЕТ
Работает ли это ПО неправильно?
ДА
Тестирование
=
Разрушение
Марат Ахин (СПбПУ) Intro 2016 8 / 359
Кому помогает тестирование?
Лучший друг верификации и валидации ПО
В чем разница?
Верификация – «мы сделали это правильно»
Валидация – «мы сделали то, что надо»
Марат Ахин (СПбПУ) Intro 2016 9 / 359
Можем ли мы что-то гарантировать при тестировании?
Данное ПО никогда не упадет
Потоки никогда не заблокируются
Вычисления всегда выполняются корректно
Временные характеристики всегда выдерживаются
Мы можем дать такие гарантии лишь в самых тривиальных случаях,
когда обычно все ясно и без тестирования
Марат Ахин (СПбПУ) Intro 2016 10 / 359
Можем ли мы что-то гарантировать при тестировании?
Данное ПО никогда не упадет
Потоки никогда не заблокируются
Вычисления всегда выполняются корректно
Временные характеристики всегда выдерживаются
Мы можем дать такие гарантии лишь в самых тривиальных случаях,
когда обычно все ясно и без тестирования
Марат Ахин (СПбПУ) Intro 2016 10 / 359
Почему тестировать сложно?
Brian Kernighan
«Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by
definition, not smart enough to debug it.»
Massimo Arnoldi (feat. Kent Beck)
«Unfortunately at least for me (and not only) testing goes against human
nature. If you realize the pig in you, you will see that you program without
tests.»
Марат Ахин (СПбПУ) Intro 2016 11 / 359
Почему тестировать нужно?
Если отложить сегодняшние дела на послезавтра, у вас появятся два
свободных дня! (с)
Марат Ахин (СПбПУ) Intro 2016 12 / 359
Что же делать?
Марат Ахин (СПбПУ) Intro 2016 13 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
Тестирование ПО с точки зрения дилетанта
Модель программной ошибки
Модель тестирования ПО
Процесс тестирования ПО
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
6 Разработка через тестирование
7 Интеграционное тестированиеМарат Ахин (СПбПУ) Intro 2016 14 / 359
Тестирование ПО с точки зрения дилетанта
Запустили приложение
Проверили результаты выполнения на предмет наличия в них
ошибок
aka «багов»
aka «сбоев»
aka «дефектов»
aka «неудач»
Сперва надо разобраться, а что же такое «программная ошибка»?
Марат Ахин (СПбПУ) Intro 2016 15 / 359
Модель программной ошибки
FAILURE
FAULT
ERROR
Неудача – наблюдаемое снаружи
некорректное поведение программы
Сбой – некорректное состояние
программы из-за ошибки
Ошибка – ошибка в самой
программе, внесенная на этапе
разработки
Рассмотрим данную модель на примере
Марат Ахин (СПбПУ) Intro 2016 16 / 359
Модель программной ошибки
Найдите ошибку в следующей программе на Java
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Возможное переполнение в строке 4
Марат Ахин (СПбПУ) Intro 2016 17 / 359
Модель программной ошибки
Найдите ошибку в следующей программе на Java
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Возможное переполнение в строке 4
Марат Ахин (СПбПУ) Intro 2016 17 / 359
Модель программной ошибки
c = {}
Что будет?
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Нет ни сбоя, ни неудачи – программа работает корректно
Марат Ахин (СПбПУ) Intro 2016 18 / 359
Модель программной ошибки
c = {}
Что будет?
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Нет ни сбоя, ни неудачи – программа работает корректно
Марат Ахин (СПбПУ) Intro 2016 18 / 359
Модель программной ошибки
c = {1, 2, 3, 5}
Что будет?
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Нет ни сбоя, ни неудачи – программа работает корректно
Марат Ахин (СПбПУ) Intro 2016 19 / 359
Модель программной ошибки
c = {1, 2, 3, 5}
Что будет?
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Нет ни сбоя, ни неудачи – программа работает корректно
Марат Ахин (СПбПУ) Intro 2016 19 / 359
Модель программной ошибки
c = {1, 2, 3, 5, Integer.MAX_VALUE, Integer.MIN_VALUE}
Что будет?
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Сбой есть – программа проходит через некорректное состояние
Но неудачи нет – результат работы программы корректен
Марат Ахин (СПбПУ) Intro 2016 20 / 359
Модель программной ошибки
c = {1, 2, 3, 5, Integer.MAX_VALUE, Integer.MIN_VALUE}
Что будет?
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Сбой есть – программа проходит через некорректное состояние
Но неудачи нет – результат работы программы корректен
Марат Ахин (СПбПУ) Intro 2016 20 / 359
Модель программной ошибки
c = {1, 2, 3, 5, Integer.MAX_VALUE}
Что будет?
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Сбой есть – программа проходит через некорректное состояние
Неудача тоже есть – результат работы программы неправильный
Марат Ахин (СПбПУ) Intro 2016 21 / 359
Модель программной ошибки
c = {1, 2, 3, 5, Integer.MAX_VALUE}
Что будет?
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Сбой есть – программа проходит через некорректное состояние
Неудача тоже есть – результат работы программы неправильный
Марат Ахин (СПбПУ) Intro 2016 21 / 359
Что мы делали?
Запускали ПО (мысленно)
Сравнивали результаты работы с ожидаемыми (логически)
Можно ли придумать другой способ тестирования?
Марат Ахин (СПбПУ) Intro 2016 22 / 359
Модель тестирования ПО
Эталонная модель может быть
представлена множеством различных
способов
неформальное представление о том,
«как должна работать программа»
формальная техническая
спецификация
набор тестовых примеров
корректные результаты работы
программы
другая (априори корректная)
реализация той же исходной
спецификации
Марат Ахин (СПбПУ) Intro 2016 23 / 359
Процесс тестирования ПО
Что может случиться?
Марат Ахин (СПбПУ) Intro 2016 24 / 359
Тест прошел
A-WE-SO-ME!
Марат Ахин (СПбПУ) Intro 2016 25 / 359
Тест не прошел
OH-MI-GOD!
Марат Ахин (СПбПУ) Intro 2016 26 / 359
Ошибка в ПО
Все просто и понятно, да?
Марат Ахин (СПбПУ) Intro 2016 27 / 359
Ошибка в эталонной модели
Некорректный тест? Ошибка в спецификации?
Марат Ахин (СПбПУ) Intro 2016 28 / 359
Ошибка в тестовом окружении
Баг в тестовой библиотеке?
Марат Ахин (СПбПУ) Intro 2016 29 / 359
Ошибка в платформе
Баг в ОС? Аппаратный сбой? Ошибка компилятора?
Марат Ахин (СПбПУ) Intro 2016 30 / 359
Процесс тестирования ПО
Является ли данная модель самодостаточной?
Марат Ахин (СПбПУ) Intro 2016 31 / 359
Процесс тестирования ПО
Откуда брать эталонную модель?
Как сравнивать результаты работы программы и модели?
Марат Ахин (СПбПУ) Intro 2016 32 / 359
Процесс тестирования ПО
Когда останавливать процесс тестирования?
Марат Ахин (СПбПУ) Intro 2016 33 / 359
Процесс тестирования ПО
Как подобрать входные данные, чтобы:
дойти до места с программной ошибкой (Reachibility)
испортить состояние программы с появлением сбоя (Corruption)
вызвать неудачу в работе программы (Propagation)
Марат Ахин (СПбПУ) Intro 2016 34 / 359
Проблемы тестирования
What’s up, Doc? (с)
Проблема тестовых входных данных
Проблема наблюдаемости
Проблема «останова»
Проблема тестового оракула
Марат Ахин (СПбПУ) Intro 2016 35 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
Модели разработки ПО
Проблемы тестирования ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
6 Разработка через тестирование
7 Интеграционное тестирование
Марат Ахин (СПбПУ) Intro 2016 36 / 359
Модели разработки ПО
Чем активнее используется тестирование в процессе разработки,
тем важнее его правильное использование
Марат Ахин (СПбПУ) Intro 2016 37 / 359
Водопадная модель
Строго последовательная модель
разработки
Тестирование выполняется над всей
программой сразу
Имеется хорошая эталонная модель
Стоимость поиска и исправления
ошибок очень высока
Марат Ахин (СПбПУ) Intro 2016 38 / 359
Инкрементальная модель
Разработка проходит в несколько
итераций
Тестируются отдельные версии
программы
Имеется неплохая эталонная модель
Стоимость поиска и исправления
ошибок высока
Марат Ахин (СПбПУ) Intro 2016 39 / 359
Гибкая модель
Все этапы разработки неразрывно
связаны друг с другом
Тестированию подвергаются как сама
программа, так и ее компоненты
Эталонная модель есть не всегда
Стоимость поиска и исправления
ошибок относительно низка
Марат Ахин (СПбПУ) Intro 2016 40 / 359
Проблемы тестирования ПО
Разве что-то может пойти совсем плохо?
Марат Ахин (СПбПУ) Intro 2016 41 / 359
Розовые очки
Марат Ахин (СПбПУ) Intro 2016 42 / 359
Розовые очки
Неправильное тестирование создает иллюзию, что все хорошо...
...тогда как на самом деле все может быть очень и очень плохо
Все тесты проходят
Выпускаем код в релиз
...
BOOM!
Марат Ахин (СПбПУ) Intro 2016 43 / 359
Наводнение
Марат Ахин (СПбПУ) Intro 2016 44 / 359
Наводнение
Неправильное тестирование создает иллюзию, что все плохо...
...тогда как на самом деле все вполне себе ничего
Большинство тестов не проходит
Садимся и исправляем ошибки
...
UNREACHABLE!
Марат Ахин (СПбПУ) Intro 2016 45 / 359
Прятки
Марат Ахин (СПбПУ) Intro 2016 46 / 359
Прятки
Неправильное тестирование создает иллюзию, что все плохо...
...тогда как на самом деле все плохо в другом месте
Некоторые тесты не проходит
Садимся и ищем ошибки
...
HUH?
Марат Ахин (СПбПУ) Intro 2016 47 / 359
Что же делать?
Марат Ахин (СПбПУ) Intro 2016 48 / 359
Что же делать?
Марат Ахин (СПбПУ) Intro 2016 49 / 359
W.I.L.T.
Марат Ахин (СПбПУ) Intro 2016 50 / 359
Проблема тестовых входных данных
Software Testing 101
Марат Ахин
Санкт-Петербургский политехнический университет
2016
Марат Ахин (СПбПУ) Input 2016 51 / 359
Quiz
Марат Ахин (СПбПУ) Input 2016 52 / 359
Recap
Марат Ахин (СПбПУ) Input 2016 53 / 359
Проблемы тестирования
What’s up, Doc? (с)
Проблема тестовых входных данных
Проблема наблюдаемости
Проблема «останова»
Проблема тестового оракула
Марат Ахин (СПбПУ) Input 2016 54 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
Обеспечение достижимости
Входные данные
Тестовые данные
Классы эквивалентности
5 Проблема неявных входных данных
6 Разработка через тестирование
7 Интеграционное тестированиеМарат Ахин (СПбПУ) Input 2016 55 / 359
Обеспечение достижимости
Какими способами можно управлять выполнением кода?
Изменением входных данных
Изменением самого исходного кода
Какой способ можно использовать для обеспечения достижимости
(reachability)?
Марат Ахин (СПбПУ) Input 2016 56 / 359
Обеспечение достижимости
Какими способами можно управлять выполнением кода?
Изменением входных данных
Изменением самого исходного кода
Какой способ можно использовать для обеспечения достижимости
(reachability)?
Марат Ахин (СПбПУ) Input 2016 56 / 359
Обеспечение достижимости
Какими способами можно управлять выполнением кода?
Изменением входных данных
Изменением самого исходного кода
Какой способ можно использовать для обеспечения достижимости
(reachability)?
Марат Ахин (СПбПУ) Input 2016 56 / 359
Обеспечение достижимости
Какими способами можно управлять выполнением кода?
Изменением входных данных
Изменением самого исходного кода
Какой способ можно использовать для обеспечения достижимости
(reachability)?
Марат Ахин (СПбПУ) Input 2016 56 / 359
Входные данные
Что такое входные данные?
Марат Ахин (СПбПУ) Input 2016 57 / 359
Входные данные
Файлы
Фактические аргументы функций
Сетевые пакеты
Результаты запроса к БД
Последовательность вызовов функций
Конфигурация ПО
Марат Ахин (СПбПУ) Input 2016 58 / 359
Тестовые данные
Почему бы просто не перебрать все возможные варианты?
1 int add(int a, int b) { ... }
18,446,744,073,709,551,616 вариантов
А если у тестируемого модуля есть внутреннее состояние?
Марат Ахин (СПбПУ) Input 2016 59 / 359
Тестовые данные
Марат Ахин (СПбПУ) Input 2016 60 / 359
Классы эквивалентности
Все пространство входных состояний можно разбить на
множество классов эквивалентности
Каждый класс эквивалентности обрабатывается тестируемым
модулем одинаково с точки зрения спецификации
Тестирование всех классов эквивалентности позволяет найти
ошибки прямого нарушения спецификации
Как найти классы эквивалентности?
Марат Ахин (СПбПУ) Input 2016 61 / 359
Ad hoc testing
Тестирование методом «научного тыка»
Запускаем ПО
Смотрим на результаты работы
...
PROFIT!
Марат Ахин (СПбПУ) Input 2016 62 / 359
Ad hoc testing
А что будет, если я нажму на эту
кнопочку?
Если сложить два положительных
числа, то...
После умножения на ноль в
результате должен получится ноль
Если ввести очень большое число и
удвоить его, то...
В чем проблемы при таком подходе к тестированию?
Марат Ахин (СПбПУ) Input 2016 63 / 359
Метод свободного поиска
Ad hoc testing + планирование
Описываем тест-план
Проверяем ПО на соответствие тест-плану
...
PROFIT!
Марат Ахин (СПбПУ) Input 2016 64 / 359
Метод свободного поиска
Если ввести число «42», потом
нажать «+», потом ввести «1» и
нажать «=», в результате должно
получиться «43»
Многократные нажатия на «C» не
должны приводить к видимым
изменениям в интерфейсе
В чем проблемы при таком подходе к тестированию?
Марат Ахин (СПбПУ) Input 2016 65 / 359
Анализ граничных значений
Баю баюшки баю, не ложися на краю...
Находим пограничные значения входных данных
Проверяем ПО вокруг выбранных пограничных значений
...
PROFIT!
Марат Ахин (СПбПУ) Input 2016 66 / 359
Анализ граничных значений
Если умножить любое число на «0»,
должен получиться «0»
Деление любого числа на «0»
должно приводить к выводу
соответствующей ошибки
Если изменить знак наибольшего
представимого положительного
числа, должно получиться
соответствующее ему отрицательное
число
В чем проблемы при таком подходе к тестированию?
Марат Ахин (СПбПУ) Input 2016 67 / 359
Примеры
kd-tree
stoi
md5sum
PDF reader
Марат Ахин (СПбПУ) Input 2016 68 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
Неявные входные данные
Использование заглушек
6 Разработка через тестирование
7 Интеграционное тестирование
Марат Ахин (СПбПУ) Input 2016 69 / 359
Неявные входные данные
Покрывает ли спецификация все множество входных данных?
В некоторых случаях – да
В большинстве случаев – нет
Почему?
Проблема заключается в том, что на тестовый модуль, кроме
явных, влияет множество неявных входных данных
Неявные входные данные часто не находят отражения в
спецификации
Марат Ахин (СПбПУ) Input 2016 70 / 359
Неявные входные данные
Текущая дата/время
IP/MAC адрес
Локаль пользователя
Идентификаторы устройств
Контекстные переключения/планирование нитей
Скорость поступления IP пакетов
Ритм нажатия клавиш на клавиатуре
Все это – примеры неявных входных данных
Марат Ахин (СПбПУ) Input 2016 71 / 359
Therac-25
Марат Ахин (СПбПУ) Input 2016 72 / 359
Robot pharmacist
Марат Ахин (СПбПУ) Input 2016 73 / 359
Как учесть неявные входные данные?
Какими способами можно управлять выполнением кода?
Изменением входных данных
Изменением самого исходного кода
Simulate and Stub
Заменяем части модуля управляемыми заглушками
Это позволяет сделать неявные входные данные явными
Это также делает управление явными входными данными проще
Марат Ахин (СПбПУ) Input 2016 74 / 359
Использование заглушек
Данный подход позволяет:
имитировать возникновение редких ситуаций
внести детерминизм там, где его нет
Для того, чтобы можно было использовать S&S, тестируемый
модуль должен разрабатываться соответствующим образом
Марат Ахин (СПбПУ) Input 2016 75 / 359
Mock-объекты
Пример S&S – mock-объекты
Повторяют внешний интерфейс тестируемого объекта
Могут демонстрировать любое требуемое поведение
Марат Ахин (СПбПУ) Input 2016 76 / 359
Mockito
1 @Test
2 void testFoo () {
3 List mockedList = mock(List.class );
4
5 when(mockedList.get (0)). thenReturn("first");
6 when(mockedList.get (1)). thenReturn("second");
7
8 assertEquals ("first", mockedList.get (0));
9 assertEquals ("second", mockedList.get (1));
10 assertEquals (null , mockedList.get (42));
11 }
Марат Ахин (СПбПУ) Input 2016 77 / 359
Mockito
Сервис аутентификации и авторизации
Вход пользователя с корректными логином/паролем должен
приводить к переходу его учетной записи в активное состояние
Марат Ахин (СПбПУ) Input 2016 78 / 359
Mockito
1 @Test
2 void testLoginForValidUser () {
3 IPasswordInfo passInfo = mock( IPasswordInfo .class );
4 when(passInfo.matches(anyString ())). thenReturn(true );
5
6 IAccount account = mock(IAccount.class );
7 when(account. getPasswordInfo ()). thenReturn(passInfo );
8
9 IAccountRepository repo = mock( IAccountRepository .class );
10 when(repo.find(anyString (), anyString ())). thenReturn(account );
11
12 AuthService service = new AuthService(repo );
13 service.login("marat", "password2");
14
15 verify(account ). setLoggedIn (true );
16 }
Марат Ахин (СПбПУ) Input 2016 79 / 359
Mockito
Сервис аутентификации и авторизации
Три последовательные попытки входа пользователя с
некорректным паролем должны приводить к блокированию его
учетной записи
Марат Ахин (СПбПУ) Input 2016 80 / 359
Mockito
1 @Test
2 void testBlockOnIncorrectLogin () {
3 IPasswordInfo passInfo = mock( IPasswordInfo .class );
4 when(passInfo.matches(anyString ())). thenReturn(false );
5
6 IAccount account = mock(IAccount.class );
7 when(account. getPasswordInfo ()). thenReturn(passInfo );
8
9 IAccountRepository repo = mock( IAccountRepository .class );
10 when(repo.find(anyString (), anyString ())). thenReturn(account );
11
12 AuthService service = new AuthService(repo );
13 service.login("bob", "111");
14 service.login("bob", "123");
15 service.login("bob", "321");
16
17 verify(account ). setBlocked(true );
18 }
Марат Ахин (СПбПУ) Input 2016 81 / 359
Mockito
1 @Test
2 void testBlockOnIncorrectLoginPerAccount () {
3 IPasswordInfo aliceInfo = getMockedPasswordInfo (false );
4 IPasswordInfo bobInfo = getMockedPasswordInfo (false );
5
6 IAccount aliceAcc = getMockedAccount (aliceInfo );
7 IAccount bobAcc = getMockedAccount (bobInfo );
8
9 IAccountRepository repo = mock( IAccountRepository .class );
10 when(repo.find("alice", anyString ())). thenReturn(aliceAcc );
11 when(repo.find("bob", anyString ())). thenReturn(bobAcc );
12
13 AuthService service = new AuthService(repo );
14 service.login("bob", "111");
15 service.login("alice", "111");
16 service.login("bob", "123");
17 service.login("alice", "123");
18 service.login("bob", "321");
19
20 verify(aliceAcc , never ()). setBlocked(true );
21 verify(bobAcc , times (1)). setBlocked(true );
22 }
Марат Ахин (СПбПУ) Input 2016 82 / 359
Mocks = Stubs = Fakes = Dummies
Разве есть разница?
Dummies
Объект-муляж, не обладающий собственным поведением
Fakes
Упрощенная реализация требуемой функциональности
Stubs
Тестовая заглушка, способная отвечать на внешние запросы
Mocks
Тестовая загрушка, способная отвечать на внешние запросы и
проверять их корректность
Марат Ахин (СПбПУ) Input 2016 83 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
6 Разработка через тестирование
Test-driven development
Плюсы TDD
Минусы TDD
7 Интеграционное тестирование
Марат Ахин (СПбПУ) Input 2016 84 / 359
Нужны ли заглушки?
А как использовать mock-объекты в процессе разработки?
Для управления неявными входными данными
Для управления явными входными данными
А когда их следует использовать?
Марат Ахин (СПбПУ) Input 2016 85 / 359
Заглушки не нужны?
Никогда!
Зачем тратить время на разработку и использование заглушек?
Можно просто подождать, пока не будут разработаны все
компоненты
Получится проще, дешевле и лучше, чем с заглушками!
Марат Ахин (СПбПУ) Input 2016 86 / 359
Заглушки не нужны?
Все же будет хорошо, да?
Марат Ахин (СПбПУ) Input 2016 87 / 359
Заглушки нужны?
Чем дольше итерация, тем сложнее и дороже исправление ошибок
Чем быстрее будут написаны тесты для разрабатываемого
компонента, тем проще найти ошибки
После разработки компонента пишем для него тест
Отсутствующие части системы заменяем заглушками
...
PROFIT!
Марат Ахин (СПбПУ) Input 2016 88 / 359
Заглушки нужны?
А давайте писать тесты еще быстрее?
Марат Ахин (СПбПУ) Input 2016 89 / 359
Test-driven development
Пишем тест для компонента перед его разработкой
Заменяем сам компонент заглушкой
...
PROFIT???
Разве это будет работать?
Марат Ахин (СПбПУ) Input 2016 90 / 359
Test-driven development
Разве это будет работать?
Марат Ахин (СПбПУ) Input 2016 91 / 359
Плюсы TDD
Разработка ведется небольшими контролируемыми фрагментами
В каждый момент времени разработчик думает об ограниченном
фрагменте спецификации
Это упрощает анализ возможного пространства входных данных
Кроме того, код получается более модульным и расширяемым
Марат Ахин (СПбПУ) Input 2016 92 / 359
Плюсы TDD
Минимальная цена ошибки
В случае возникновения ошибки очень просто вернуть систему в
рабочее состояние
Практически отсутствует необходимость в отладке
Крайне просто использовать метод бисекции в случае, если
ошибка смогла пробраться в релиз
Марат Ахин (СПбПУ) Input 2016 93 / 359
Плюсы TDD
Ошибки обнаруживаются сразу же после их появления
Постоянный запуск тестов гарантирует практически моментальное
обнаружение ошибки
Малый размер тестов позволяет быстро найти причину ошибки
Марат Ахин (СПбПУ) Input 2016 94 / 359
Плюсы TDD
Сильно упрощается рефакторинг кода
Программист уверен в том, что его изменения ничего не ломают
Облегчается раздельное владение кодом
Марат Ахин (СПбПУ) Input 2016 95 / 359
Почему я слышу о TDD впервые в жизни?
Почему TDD не используют везде и всюду?!
Марат Ахин (СПбПУ) Input 2016 96 / 359
Минусы TDD
Синдром «розовых очков»
Большое количество тестов создает иллюзию бесконечной
надежности системы тестирования
При создании теста разработчик может сделать те же допущения,
что и при разработке самого компонента
Марат Ахин (СПбПУ) Input 2016 97 / 359
Минусы TDD
Поддержание тестов в актуальном состоянии
При внесении изменений в интерфейсы компонентов системы
необходимо соответствующим образом изменить и все тесты
Большое количество тестов приводит к значительным затратам
на рефакторинг тестов
Марат Ахин (СПбПУ) Input 2016 98 / 359
Минусы TDD
Невозможность тестирования сложного взаимодействия нескольких
компонентов
Каждый тест проверяет ограниченный фрагмент
функциональности системы
Взаимодействие компонентов затрагивает множество аспектов
системы сразу
Марат Ахин (СПбПУ) Input 2016 99 / 359
Стоит ли использовать TDD?
Марат Ахин (СПбПУ) Input 2016 100 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
6 Разработка через тестирование
7 Интеграционное тестирование
Проблема «Большого Взрыва»
Нисходящее интеграционное тестирование
Восходящее интеграционное тестирование
Марат Ахин (СПбПУ) Input 2016 101 / 359
Проблема «Большого Взрыва»
Когда приходит время заменять заглушки на реализацию...
Марат Ахин (СПбПУ) Input 2016 102 / 359
Проблема «Большого Взрыва»
Поведение реализации может (и скорее всего будет) отличаться
от поведения заглушки
Если заглушек было много...
Марат Ахин (СПбПУ) Input 2016 103 / 359
Проблема «Большого Взрыва»
Каскадное распространение сбоев
Сложность локализации ошибок
Большая стоимость исправления ошибок
Что мы можем сделать?
Марат Ахин (СПбПУ) Input 2016 104 / 359
Интеграционное тестирование
Ускорить процесс замены заглушек на реализацию
Выполнять тестирование взаимодействия постоянно, в процессе
разработки
Заменять заглушки на реализацию инкрементально
Инкрементальное интеграционное тестирование
Марат Ахин (СПбПУ) Input 2016 105 / 359
Интеграционное тестирование
Марат Ахин (СПбПУ) Input 2016 106 / 359
Нисходящее интеграционное тестирование
Тестирование начинается с верхних уровней системы
Отсутствующие на данный момент модули заменяются
«заглушками»
По мере реализации новых модулей они подключаются к системе
вместо «заглушек»
Марат Ахин (СПбПУ) Input 2016 107 / 359
Нисходящее интеграционное тестирование
Преимущества
Возможность ранней проверки корректности высокоуровневого
поведения
Модули могут добавляться по одному, независимо друг от друга
Не требуется разработка множества драйверов
Можно разрабатывать систему как в глубину, так и в ширину
Марат Ахин (СПбПУ) Input 2016 108 / 359
Нисходящее интеграционное тестирование
Недостатки
Отложенная проверка низкоуровневого поведения
Требуется разработка «заглушек»
Крайне сложно корректно сформулировать требования ко
входам/выходам частичной системы
Марат Ахин (СПбПУ) Input 2016 109 / 359
Восходящее интеграционное тестирование
Тестирование начинается с нижних уровней системы
Отсутствующие на данный момент модули заменяются
драйверами
При реализации всех модулей нижнего уровня драйвер может
быть заменен на соответствующий модуль
Марат Ахин (СПбПУ) Input 2016 110 / 359
Восходящее интеграционное тестирование
Преимущества
Возможность ранней проверки корректности низкоуровневого
поведения
Не требуется написание заглушек
Просто определить требования ко входам/выходам модулей
Марат Ахин (СПбПУ) Input 2016 111 / 359
Восходящее интеграционное тестирование
Недостатки
Отложенная проверка высокоуровневого поведения
Требуется разработка драйверов
При замене драйвера на модуль высокого уровня может
произойти «мини-Большой Взрыв»
Марат Ахин (СПбПУ) Input 2016 112 / 359
Проблемы тестирования
What’s up, Doc? (с)
Проблема тестовых входных данных
Проблема наблюдаемости
Проблема «останова»
Проблема тестового оракула
Марат Ахин (СПбПУ) Input 2016 113 / 359
Обеспечение порчи внутреннего состояния
Для того, чтобы обеспечить порчу внутреннего состояния
(corruption), необходимо:
обеспечить достижимость
передать такие тестовые входные данные, которые вызывают
нарушение целостности внутреннего состояния
См. проблему тестовых входных данных
Марат Ахин (СПбПУ) Input 2016 114 / 359
W.I.L.T.
Марат Ахин (СПбПУ) Input 2016 115 / 359
Проблема наблюдаемости
Software Testing 101
Марат Ахин
Санкт-Петербургский политехнический университет
2016
Марат Ахин (СПбПУ) PP 2016 116 / 359
Quiz
Марат Ахин (СПбПУ) PP 2016 117 / 359
Recap
Марат Ахин (СПбПУ) PP 2016 118 / 359
Проблемы тестирования
What’s up, Doc? (с)
Проблема тестовых входных данных
Проблема наблюдаемости
Проблема «останова»
Проблема тестового оракула
Марат Ахин (СПбПУ) PP 2016 119 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
6 Разработка через тестирование
7 Интеграционное тестирование
8 Проблема наблюдаемости
Обеспечение распространения сбоя
Марат Ахин (СПбПУ) PP 2016 120 / 359
Обеспечение распространения сбоя
Какими способами можно управлять выполнением кода?
Изменением входных данных
Изменением самого исходного кода
Необходимо обнаружить сбой и распространить его, сделав
наблюдаемым снаружи (Propagation)
Марат Ахин (СПбПУ) PP 2016 121 / 359
Обеспечение распространения сбоя
Марат Ахин (СПбПУ) PP 2016 122 / 359
Assertions
Основной способ обеспечения наблюдаемости – assertions
1 private void checkInvariants () {
2 assert elements[tail] == null;
3 assert head == tail
4 ? elements[head] == null
5 : (elements[head] != null &&
6 elements [( tail - 1) & (elements.length - 1)] != null );
7 assert elements [( head - 1) & (elements.length - 1)] == null;
8 }
Марат Ахин (СПбПУ) PP 2016 123 / 359
Assertions
Что такое assertion?
Формула в логике первого порядка
Проверяется на истинность во время выполнения программы
Также может проверяться на истинность статически
Допускает возможность отключения проверки истинности
Марат Ахин (СПбПУ) PP 2016 124 / 359
Что дает использование assertions?
Проверка корректности внутреннего состояния
Внутреннее состояние обычно недоступно снаружи (полностью
или частично)
При изменении состояния хочется проверить, что оно остается
корректным
Марат Ахин (СПбПУ) PP 2016 125 / 359
Что дает использование assertions?
Неудача происходит ближе к причине ее возникновения
Чем больше задержка перед обнаружением неудачи, тем сложнее
найти ее исходную причину
Assertions позволяют найти неудачу практически в любой точке
программы
Марат Ахин (СПбПУ) PP 2016 126 / 359
Что дает использование assertions?
Явное документирование пред- и пост-условий
В общем случае программист ничего не знает о контракте
используемой функции
Использование assertions позволяет в явном виде описать
внешний контракт функции
Марат Ахин (СПбПУ) PP 2016 127 / 359
Assertions
Марат Ахин (СПбПУ) PP 2016 128 / 359
Какие проблемы связаны с assertions?
Ошибки в assertions
Побочные эффекты в assertions
Неправильное логическое условие срабатывания
Марат Ахин (СПбПУ) PP 2016 129 / 359
Какие проблемы связаны с assertions?
Влияние на производительность
Проверка assertions занимает время
Чем сложнее assertion, тем больше он замедляет работу
программы
Марат Ахин (СПбПУ) PP 2016 130 / 359
Какие проблемы связаны с assertions?
Эффект «вышибалы»
Сработавший assertion превращает любую ошибку в неудачу
Это полностью останавливает возможность дальнейшего
тестирования
Марат Ахин (СПбПУ) PP 2016 131 / 359
Какие проблемы связаны с assertions?
Сложность проверки определенных условий
Некоторые просто формулируемые условия крайне сложно
проверить на практике
Их реализация в виде assertion является крайне затруднительной
Марат Ахин (СПбПУ) PP 2016 132 / 359
Работают ли assertions?
Марат Ахин (СПбПУ) PP 2016 133 / 359
Работают ли assertions?
1 int* ptr = malloc(sizeof(int) * 10);
2 assert(ptr);
Адекватный assertion в правильном месте
Марат Ахин (СПбПУ) PP 2016 134 / 359
Работают ли assertions?
1 int* ptr = malloc(sizeof(int) * 10);
2 assert(ptr);
Замена обработки ошибок на assertion
Марат Ахин (СПбПУ) PP 2016 135 / 359
Работают ли assertions?
Марат Ахин (СПбПУ) PP 2016 136 / 359
Работают ли assertions?
Microsoft Office ≈ 1%
Proprietary software ≈ 3%
Open source software ≈ 5%
Eiffel software ≈ 7%
Сейчас assertions используются еще более широко
Марат Ахин (СПбПУ) PP 2016 137 / 359
Работают ли assertions?1
LLVM
≈ 500,000 SLOC
≈ 7000 assertions
> 400 ошибок, относящихся к assertions
1
http://blog.regehr.org/
Марат Ахин (СПбПУ) PP 2016 138 / 359
Работают ли assertions?1
GCC
≈ 1,000,000 SLOC
≈ 9500 assertions
> 200 ошибок, относящихся к assertions
1
http://blog.regehr.org/
Марат Ахин (СПбПУ) PP 2016 138 / 359
Работают ли assertions?2
1 assert( BlockAddrFwdRefs .empty () && ...);
2 assert(Ty == V->getType () && ...);
3 assert ((Ty == 0 || Ty == V->getType ()) && ...);
4 assert(It != ResolveConstants .end() && ...);
5 assert(isa <ConstantExpr >( UserC) && ...);
6 assert(V->getType ()-> isMetadataTy () && ...);
7 assert ((! Alignment || isPowerOf2_32 (Alignment )) && ...);
8 assert (( Record[i] == 3 || Record[i] == 4) && ...);
9 assert(Record[i] == 0 && ...);
10 assert(Record[i] == 0 && ...);
11 assert(ResultTy && ...);
12 assert(TypeList[NumRecords] == 0 && ...);
13 assert(NextBitCode == bitc :: METADATA_NAMED_NODE );
14 assert ((CT != LandingPadInst :: Catch
15 || !isa <ArrayType >(Val ->getType ())) && ...);
16 assert ((CT != LandingPadInst :: Filter
17 || isa <ArrayType >(Val ->getType ())) && ...);
18 assert(DFII != DeferredFunctionInfo .end () && ...);
19 assert( DeferredFunctionInfo .count(F) && ...);
20 assert(M == TheModule && ...);
2
http://blog.regehr.org/
Марат Ахин (СПбПУ) PP 2016 139 / 359
Журналирование
Марат Ахин (СПбПУ) PP 2016 140 / 359
Журналирование
Журналирование (logging)
Запись хода выполнения программы в том или ином виде
В зависимости от необходимости журнал может быть более или
менее детализированным
По журналу выполнения при необходимости возможно
восстановить причину возникшей ошибки
Марат Ахин (СПбПУ) PP 2016 141 / 359
Журналирование
Журналирование для
пользователя
Высокоуровневые
сообщения
Как можно меньше
«мусора»
Чем проще и понятнее
формат сообщений, тем
лучше
Журналирование для
программиста
Низкоуровневые
сообщения
Допустим любой шум
Никаких ограничений на
формат сообщений
Марат Ахин (СПбПУ) PP 2016 142 / 359
Как вести журнал?
1 Result :: Ptr processBatchJob (Job :: Ptr job) {
2 // do the heavy lifting ...
3 }
Как записать ход выполнения программы?
Марат Ахин (СПбПУ) PP 2016 143 / 359
Как вести журнал?
1 Result :: Ptr ThreadedProcessor :: processBatchJob (Job:: Ptr job) {
2 log () << "Start of: " << job << endl;
3 // do the heavy lifting ...
4 log () << "End of: " << job << endl;
5 }
Ручная вставка журналирующих вызовов
Марат Ахин (СПбПУ) PP 2016 144 / 359
Как вести журнал?
1 aspect ProcessTracer {
2 advice call("% %Processor :: process %(%)") : before () {
3 log () << "Start of: " << * JoinedPoint ::arg <0 >() << endl;
4 }
5 advice call("% %Processor :: process %(%)") : after () {
6 log () << "End of: " << *JoinedPoint ::arg <0 >() << endl;
7 }
8 };
Журналирующие аспекты / интерсепторы
Марат Ахин (СПбПУ) PP 2016 145 / 359
Как вести журнал?
Logging as a Service
Марат Ахин (СПбПУ) PP 2016 146 / 359
Основная проблема журналирования
INFO [http -thread -pool -8080(5)] Received token: e6749451
TRACE [http -thread -pool -8080(5)] Calling: AuthStorageBean . getAuthData
TRACE [http -thread -pool -8080(5)] Called: AuthStorageBean .getAuthData -> 2.0708E-5
INFO [http -thread -pool -8080(5)] Authentication data found: AuthData { authToken:e6749451
userId :1 firstName: lastName:Admin patrName: role:ru.korus.tmis.core.entity.model.
Role[id=1] spec: }
TRACE [http -thread -pool -8080(5)] Calling: AuthStorageBean . getAuthDateTime
TRACE [http -thread -pool -8080(5)] Called: AuthStorageBean . getAuthDateTime -> 1.9825E-5
INFO [http -thread -pool -8080(5)] Token is valid
TRACE [http -thread -pool -8080(5)] attempting to get session; create = false; session is
null = true; session has id = false
TRACE [http -thread -pool -8080(5)] Authentication attempt received for token [ru.korus.tmis
.core.auth. TmisShiroToken@37bd2b6 ]
DEBUG [http -thread -pool -8080(5)] Performing credentials equality check for
tokenCredentials of type [java.lang.String and accountCredentials of type [java.lang
.String]
DEBUG [http -thread -pool -8080(5)] Both credentials arguments can be easily converted to
byte arrays. Performing array equals comparison
DEBUG [http -thread -pool -8080(5)] Authentication successful for token [ru.korus.tmis.core.
auth. TmisShiroToken@37bd2b6 ]. Returned account [(admin ,ru.korus.tmis.core.entity.
model.Role[id =1])]
DEBUG [http -thread -pool -8080(5)] No SecurityManager available in subject context map.
Falling back to SecurityUtils . getSecurityManager () lookup.
Too much data!
Марат Ахин (СПбПУ) PP 2016 147 / 359
Основная проблема журналирования
Чем больше мы хотим узнать о ходе выполнения программы, тем
больше мы должны журналировать
Чем больше мы журналируем, тем сложнее разобраться в журнале
Чем сложнее разобраться в журнале, тем меньше мы знаем о ходе
выполнения программы
Марат Ахин (СПбПУ) PP 2016 148 / 359
Ограничение размера журнала
Необходимо ограничивать размер записываемых данных
Марат Ахин (СПбПУ) PP 2016 149 / 359
Уровни журналирования
Сообщения пишутся в журнал с определенным уровнем
В дальнейшем возможно фильтровать сообщения по уровням
Error / Warning / Info / Debug / Trace
Марат Ахин (СПбПУ) PP 2016 150 / 359
Домены журналирования
Домены ортогональны уровням журналирования
В зависимости от типа сообщения пишутся в разные домены
Database / Network / UI / Configuration / ...
Марат Ахин (СПбПУ) PP 2016 151 / 359
Стохастическое журналирование
В случае, если какие-то события встречаются очень часто,
достаточно записывать лишь их часть
1 if (_ok == true) {
2 _logger.log( Level.WARNING , "Server seen down: " + _addr , e );
3 } else if (Math.random () < 0.1) {
4 _logger.log( Level.WARNING , "Server seen down: " + _addr );
5 }
Марат Ахин (СПбПУ) PP 2016 152 / 359
Сессионное журналирование
Часто работа ПО разбита на набор слабо связанных сессий
Каждая сессия может журналироваться независимо от других
1 try {
2 // logging ...
3 } catch (Exception ex) {
4 ctx.logging. dumpCurrentSession ();
5 throw;
6 } finally {
7 ctx.logging.reset ();
8 }
Марат Ахин (СПбПУ) PP 2016 153 / 359
Структурированное журналирование
Вместо простого текста журнал ведется в определенном формате
Структурированный формат облегчает поиск и анализ по журналу
1 {
2 "session_id": "e6749451",
3 "event": " method_call",
4 "class_name": " AuthStorageBean ",
5 "method_name ": "getAuthData "
6 }
Марат Ахин (СПбПУ) PP 2016 154 / 359
W.I.L.T.
Марат Ахин (СПбПУ) PP 2016 155 / 359
Полнота тестирования ПО
Software Testing 101
Марат Ахин
Санкт-Петербургский политехнический университет
2016
Марат Ахин (СПбПУ) TC 2016 156 / 359
Quiz
Марат Ахин (СПбПУ) TC 2016 157 / 359
Recap
Марат Ахин (СПбПУ) TC 2016 158 / 359
Проблемы тестирования
What’s up, Doc? (с)
Проблема тестовых входных данных
Проблема наблюдаемости
Проблема «останова»
Проблема тестового оракула
Марат Ахин (СПбПУ) TC 2016 159 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
6 Разработка через тестирование
7 Интеграционное тестирование
8 Проблема наблюдаемости
Марат Ахин (СПбПУ) TC 2016 160 / 359
Проблема «останова» в тестировании
Проблема останова
По заданному алгоритму и входным данным определить, завершится
ли за конечное время его выполнение
При чем здесь тестирование?!
Марат Ахин (СПбПУ) TC 2016 161 / 359
Проблема «останова» в тестировании
Алгоритм ⇔ процесс тестирования
Входные данные ⇔ тестируемая программа
В подавляющем большинстве случаев процесс тестирования является
бесконечным
Марат Ахин (СПбПУ) TC 2016 162 / 359
Проблема «останова» в тестировании
Мы не можем позволить себе тестировать бесконечное время
Слишком долго
Слишком дорого
Слишком странно
Что же делать?
Марат Ахин (СПбПУ) TC 2016 163 / 359
Проблема «останова» в тестировании
Останавливать процесс тестирования «вручную»
Когда?
У нас кончилось время и/или деньги на тестирование
Мы протестировали ПО достаточно хорошо
Марат Ахин (СПбПУ) TC 2016 164 / 359
Проблема «останова» в тестировании
Проблема «останова» в тестировании
По заданному набору тестов и программе определить, протестировали
ли мы ее достаточно хорошо
Что такое – достаточно хорошо?
Марат Ахин (СПбПУ) TC 2016 165 / 359
Тестовое покрытие
Мы протестировали программу достаточно хорошо, когда мы
нашли большую часть ошибок в программе
Чтобы найти ошибку, необходимо обеспечить выполнение трех
основных свойств
Обеспечение достижимости (reachability) и порчи (corruption)
требует, чтобы мы выполнили определенный участок кода с
определенными входными данными
Качество тестирования можно оценить через тестовое покрытие
Марат Ахин (СПбПУ) TC 2016 166 / 359
Виды тестового покрытия
Выделяют два основных вида покрытия
Покрытие потока управления
Покрытие потока данных
Они работают с такими понятиями, как граф потока
управления (CFG) и граф потока данных (DFG)
Надеюсь, что все знают, что такое CFG и DFG?
Марат Ахин (СПбПУ) TC 2016 167 / 359
Покрытие потока управления
Как мы можем покрыть данный
CFG?
По узлам
По дугам
По условиям
По путям
...
Марат Ахин (СПбПУ) TC 2016 168 / 359
Покрытие операторов программы
Каждый узел CFG был пройден в
процессе тестирования хотя бы один раз
Самый слабый способ оценки тестового
покрытия
Сколько тестов требуется для того, чтобы
обеспечить полное покрытие операторов
программы для следующего примера?
Марат Ахин (СПбПУ) TC 2016 169 / 359
Покрытие ветвлений программы
Каждая ветка программы была пройдена
хотя бы один раз
Несколько более сильный способ оценки
покрытия
Сколько тестов требуется для того, чтобы
обеспечить полное покрытие ветвлений
программы для следующего примера?
Марат Ахин (СПбПУ) TC 2016 170 / 359
Покрытие ветвлений программы
Как соотносятся между собой покрытия
операторов и ветвлений?
1 Никак
2 Покрытие операторов включает покрытие
ветвлений
3 Покрытие ветвлений включает покрытие
операторов
Марат Ахин (СПбПУ) TC 2016 171 / 359
Покрытие ветвлений программы
Никак
Почему покрытие ветвлений не включает
в себя покрытие операторов?
Потому что в программе может
присутствовать «мертвый код»
Потому что в программе могут вообще
отсутствовать ветвления
Марат Ахин (СПбПУ) TC 2016 172 / 359
Покрытие условий программы
Каждое ветвление может выполняться по различным причинам
При покрытии условий программы мы требуем, чтобы все условия
ветвлений хотя бы один раз приняли значение true и false
1 if (req.isSsl () && (cfg.SslEnabled () || cfg.isDebug ())) {
2 ...
3 }
Как соотносятся между собой покрытия ветвлений и условий?
Марат Ахин (СПбПУ) TC 2016 173 / 359
Покрытие условий программы
Никак
Разные комбинации условий могут приводить к выбору одного и
того же ветвления
1 if (req. isLocalhost () || cfg.isDebug () || cfg.isDevMode ()) {
2 ...
3 }
Марат Ахин (СПбПУ) TC 2016 174 / 359
Покрытие ветвлений и условий программы
Комбинация соответствующих покрытий
Полностью их покрывает
Можно ли предложить что-то более сильное?
1 if (req.isSsl () && (cfg.SslEnabled () || cfg.isDebug ())) {
2 ...
3 }
Марат Ахин (СПбПУ) TC 2016 175 / 359
Модифицированное покрытие ветвлений и условий
Также известное как MC/DC
Является одним из обязательных условий при тестировании ПО
на уровень A в рамках DO-178B
Чем оно отличается от обычного покрытия ветвлений и условий
программы?
1 if (req.isSsl () && (cfg.SslEnabled () || cfg.isDebug ())) {
2 ...
3 }
Марат Ахин (СПбПУ) TC 2016 176 / 359
Модифицированное покрытие ветвлений и условий
Каждое условие независимо повлияло на выполнение программы
Как это проверить?
Изменить одно условие и проверить, изменилось ли ветвление
1 if (req.isSsl () && (cfg.SslEnabled () || cfg.isDebug ())) {
2 ...
3 }
Марат Ахин (СПбПУ) TC 2016 177 / 359
Полное покрытие условий программы
Полный перебор всех возможных комбинаций условий всех
возможных ветвлений
Сколько вариантов необходимо перебрать, чтобы получить полное
комбинационное покрытие для следующего примера?
1 if (req.isSsl () && (cfg.SslEnabled () || cfg.isDebug ())) {
2 ...
3 }
Марат Ахин (СПбПУ) TC 2016 178 / 359
Покрытие путей программы
Мы требуем, чтобы все возможные пути программы были
выполнены хотя бы один раз
Как данное покрытие соотносится с полным покрытием условий?
Обычно считается самым сильным типом покрытия потока
управления
Его можно было бы использовать, если бы не...
Циклы и рекурсия
Марат Ахин (СПбПУ) TC 2016 179 / 359
Покрытие путей программы
Мы требуем, чтобы все возможные пути программы были
выполнены хотя бы один раз
Как данное покрытие соотносится с полным покрытием условий?
Обычно считается самым сильным типом покрытия потока
управления
Его можно было бы использовать, если бы не...
Циклы и рекурсия
Марат Ахин (СПбПУ) TC 2016 179 / 359
Покрытие путей программы
Мы требуем, чтобы все возможные пути программы были
выполнены хотя бы один раз
Как данное покрытие соотносится с полным покрытием условий?
Обычно считается самым сильным типом покрытия потока
управления
Его можно было бы использовать, если бы не...
Циклы и рекурсия
Марат Ахин (СПбПУ) TC 2016 179 / 359
Покрытие путей программы
450 возможных путей
Марат Ахин (СПбПУ) TC 2016 180 / 359
Покрытие путей программы
450 возможных путей
Марат Ахин (СПбПУ) TC 2016 180 / 359
Покрытие путей программы
Для борьбы с этим используют несколько подходов
Один из вариантов
Требуем, чтобы тело цикла было выполнено
0
1
k
max
Объясните, почему выбраны именно эти варианты
Марат Ахин (СПбПУ) TC 2016 181 / 359
Покрытие потока данных
Что еще можно сделать?
Можно вспомнить о том, что программы работают не просто так
Основная цель работы любой программы – работа с данными
С этой точки зрения для тестирования представляет интерес
анализ таких путей выполнения программы, на которых активно
работают с данными
Сперва вспомним несколько определений
Марат Ахин (СПбПУ) TC 2016 182 / 359
Определения и использования переменных
Определение переменной (Def)
Оператор программы, в котором значение переменной v может быть
изменено
v = 42
f(&v, ...)
scanf(fmt, &v)
Использование переменной (Use)
Оператор программы, в котором значение переменной v влияет на
выполнение программы тем или иным способом
q = v + 2
g(v, ...)
if (v != NULL) ...
Марат Ахин (СПбПУ) TC 2016 183 / 359
Определения и использования переменных
Def-Use Chain
Пара (d, u) операторов программы, для которой выполняются
следующие условия
d – определение переменной v
u – использование переменной v
между d и u существует хотя бы один путь, на котором
переменная v не переопределяется
Рассмотрим данные определения на примере
Марат Ахин (СПбПУ) TC 2016 184 / 359
Пример
Марат Ахин (СПбПУ) TC 2016 185 / 359
Покрытие потока данных
Какие варианты покрытий можно предложить с использованием этих
понятий?
Покрытие всех определений
Для каждой интересующей нас переменной v должна быть
протестирована хотя бы одна Def-Use Chain от каждого
определения v до хотя бы одного использования v
Марат Ахин (СПбПУ) TC 2016 186 / 359
All-Def Coverage
Рассмотрим следующие тесты
1 → 2 → 3 → 4 → 5 → 6
Марат Ахин (СПбПУ) TC 2016 187 / 359
Покрытие потока данных
Покрытие всех использований
Для каждой интересующей нас переменной v должна быть
протестирована хотя бы одна Def-Use Chain от каждого
определения v до каждого использования v
Является ли All-Use более сильным критерием по сравнению с All-Def?
Марат Ахин (СПбПУ) TC 2016 188 / 359
All-Use Coverage
Рассмотрим следующие тесты
1 → 2 → 3 → 4 → 5 → 6
1 → 2 → 3 → 4 → 6
1 → 3 → 4 → 5 → 6
Марат Ахин (СПбПУ) TC 2016 189 / 359
Покрытие потока данных
Покрытие всех Def-Use Chain
Для каждой интересующей нас переменной v должны быть
протестированы все возможные Def-Use Chain от каждого
определения v до каждого использования v
Как соотносится All-Def-Use-Chain с покрытием всех путей программы?
Марат Ахин (СПбПУ) TC 2016 190 / 359
Пример
Марат Ахин (СПбПУ) TC 2016 191 / 359
Пример
Марат Ахин (СПбПУ) TC 2016 192 / 359
Пример
Марат Ахин (СПбПУ) TC 2016 193 / 359
Пример
Марат Ахин (СПбПУ) TC 2016 194 / 359
Другой способ оценки полноты
Какими способами можно управлять выполнением кода?
Изменением входных данных
Изменением самого исходного кода
Как можно оценить полноту тестирования, изменяя исходный код?
Марат Ахин (СПбПУ) TC 2016 195 / 359
Идеальный тест
Идеальный тест работает только на тестируемой программе
При любом изменений он перестает проходить
В этом заключается основная идея мутационного тестирования
Марат Ахин (СПбПУ) TC 2016 196 / 359
Мутационное тестирование
Исходная программа подвергается мутации, в результате
получается набор из N мутантов
После этого имеющиеся тесты запускаются на этих мутантах
Если тест не проходит на мутанте, то говорят, что тест «убивает»
этого мутанта
Доля «убитых» мутантов показывает, насколько полно данный
набор тестов покрывает нашу программу
Марат Ахин (СПбПУ) TC 2016 197 / 359
Как сделать мутанта?
Что можно сделать с исходным кодом?
Добавить новый код
Удалить старый код
Изменить существующий код
Набор синтаксических трансформаций, изменяющих исходный код
Марат Ахин (СПбПУ) TC 2016 198 / 359
Как сделать мутанта?
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Как можно мутировать данный фрагмент кода?
Марат Ахин (СПбПУ) TC 2016 199 / 359
Как сделать мутанта?
Некоторые мутанты будут синтаксически некорректны
Другие мутанты будут семантически некорректны
Оставшиеся мутанты подходят для использования в мутационном
тестировании
Какие проблемы есть у мутационного тестирования?
Марат Ахин (СПбПУ) TC 2016 200 / 359
Недостатки мутационного тестирования
Данный вид тестирования практически невозможно выполнять
вручную
Количество необходимых для оценки покрытия мутантов
пропорционально объему анализируемого ПО
Даже для небольшой программы получение достаточного числа
мутантов вручную является практически невозможным
Сильно возрастают затраты на проведение тестирования
Вместо одного запуска каждого теста требуется выполнить N
запусков
Кроме того, дополнительное время тратится на генерацию
мутантов
Марат Ахин (СПбПУ) TC 2016 201 / 359
Мутационное тестирование
Марат Ахин (СПбПУ) TC 2016 202 / 359
Мутационное тестирование
Марат Ахин (СПбПУ) TC 2016 203 / 359
Мутационное тестирование
Марат Ахин (СПбПУ) TC 2016 204 / 359
Оценка тестового покрытия
Мы же уже поговорили об оценке тестового покрытия?
Оценка тестового покрытия
программы
Оценка самого тестового
покрытия
Who observes the observer? c
Марат Ахин (СПбПУ) TC 2016 205 / 359
Оценка тестового покрытия
Какая проблема есть у покрытия потока управления?
Чувствительность к изменениям в исходном коде
Марат Ахин (СПбПУ) TC 2016 206 / 359
Оценка тестового покрытия
Какая проблема есть у покрытия потока управления?
Чувствительность к изменениям в исходном коде
Марат Ахин (СПбПУ) TC 2016 206 / 359
Нестабильность тестового покрытия
1 ...
2 if (a && b && c) {
3 ...
4 }
1 bool cond = a && b && c;
2 if (cond) {
3 ...
4 }
Что будет с покрытием MC/DC?
Марат Ахин (СПбПУ) TC 2016 207 / 359
Нестабильность тестового покрытия
Чем сильнее влияют изменения в программе на тестовое
покрытие, тем более нестабильным (fragile) является тестовое
покрытие
Чем более нестабильным является тестовое покрытие, тем менее
адекватно оно оценивает качество тестирования
Что же делать?
Марат Ахин (СПбПУ) TC 2016 208 / 359
Оценка тестового покрытия
The whole is more than the sum of its parts c
Можно применить мутационное тестирование для оценки
тестового покрытия
Ограничить набор трансформаций
Посмотреть на изменение тестового покрытия для мутантов
...
PROFIT!
Марат Ахин (СПбПУ) TC 2016 209 / 359
Оценка тестового покрытия
Какая проблема есть у мутационного тестирования?
Эквивалентные мутанты
Марат Ахин (СПбПУ) TC 2016 210 / 359
Оценка тестового покрытия
Какая проблема есть у мутационного тестирования?
Эквивалентные мутанты
Марат Ахин (СПбПУ) TC 2016 210 / 359
Эквивалентные мутанты
1 int sumCollection (final @NotNull Collection <Integer > c) {
2 int sum = 0;
3 for (int i : c) {
4 sum += i;
5 }
6 return sum;
7 }
Почему эквивалентные мутанты – это плохо?
Марат Ахин (СПбПУ) TC 2016 211 / 359
Эквивалентные мутанты
Эквивалентные мутанты «зашумляют» итоговую оценку качества
тестирования
Из-за шума снижается адекватность оценки
Что же делать?
Марат Ахин (СПбПУ) TC 2016 212 / 359
Оценка тестового покрытия
The whole is more than the sum of its parts c
Можно применить тестовое покрытие для оценки мутационного
тестирования
Для каждого мутанта записывается трасса его выполнения
У эквивалентных мутантов будут похожие трассы выполнения
...
PROFIT!
Марат Ахин (СПбПУ) TC 2016 213 / 359
W.I.L.T.
Марат Ахин (СПбПУ) TC 2016 214 / 359
Тестовый оракул: что, где, когда
Software Testing 101
Марат Ахин
Санкт-Петербургский политехнический университет
2016
Марат Ахин (СПбПУ) TO 2016 215 / 359
Quiz
Марат Ахин (СПбПУ) TO 2016 216 / 359
Recap
Марат Ахин (СПбПУ) TO 2016 217 / 359
Проблемы тестирования
What’s up, Doc? (с)
Проблема тестовых входных данных
Проблема наблюдаемости
Проблема «останова»
Проблема тестового оракула
Марат Ахин (СПбПУ) TO 2016 218 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
6 Разработка через тестирование
7 Интеграционное тестирование
8 Проблема наблюдаемости
Марат Ахин (СПбПУ) TO 2016 219 / 359
Тестовый оракул
Magic 8-ball тестирования
Марат Ахин (СПбПУ) TO 2016 220 / 359
Тестовый оракул
Марат Ахин (СПбПУ) TO 2016 221 / 359
Тестовый оракул
В чем заключается проблема тестового оракула?
Его нет!
Марат Ахин (СПбПУ) TO 2016 222 / 359
Тестовый оракул
Вид тестового оракула очень сильно зависит от того, какую
эталонную модель мы используем
kd-tree
stoi
md5sum
PDF reader
Марат Ахин (СПбПУ) TO 2016 223 / 359
Виды тестовых оракулов
Точность
vs
Полнота
Марат Ахин (СПбПУ) TO 2016 224 / 359
Точность
Способность оракула избегать ложных обнаружений
Ложные обнаружения при тестировании – лишние затраты на их
обнаружение и игнорирование
Если их будет слишком много, оракул никто не будет
использовать из-за зашумления результатов
Марат Ахин (СПбПУ) TO 2016 225 / 359
Полнота
Способность оракула находить все ошибки
Пропущенные ошибки при тестировании – дополнительные
затраты на их исправление позднее
Если оракул пропускает много ошибок, его необходимо усиливать
другими способами
Марат Ахин (СПбПУ) TO 2016 226 / 359
Виды тестовых оракулов
Варьируя используемые подходы, можно получить те или иные виды
тестовых оракулов
Слабые
Средние
Сильные
Марат Ахин (СПбПУ) TO 2016 227 / 359
Слабые оракулы
Падение
Segmentation fault
Core dump
Работают всегда
Практически ничего не говорят о причине ошибки
Марат Ахин (СПбПУ) TO 2016 228 / 359
Слабые оракулы
Сбой при работе в обычном окружении
NullPointerException
OutOfMemoryException
ClassNotFoundException
Работают при поддержке стандартной среды выполнения
Содержат определенную информацию о месте ошибки
Марат Ахин (СПбПУ) TO 2016 229 / 359
Слабые оракулы
Сбой при работе в специальном тестовом окружении
Valgrind
Предоставляют специальную среду выполнения
Позволяют весьма точно определить причину ошибок
Марат Ахин (СПбПУ) TO 2016 230 / 359
Valgrind
Фреймворк для построения средств динамического анализа
программ
Включает встроенные реализации для
Memcheck
Cachegrind
Callgrind
Helgrind
DRD
Massif
DHAT
...
Марат Ахин (СПбПУ) TO 2016 231 / 359
Слабые оракулы
Хорошая точность
Плохая полнота
Марат Ахин (СПбПУ) TO 2016 232 / 359
Средние оракулы
Assertions
Тесты
Требуют определенных усилий со стороны разработчиков
В зависимости от степени усилий, будут более или менее точно
указывать на место возникновения ошибки
Марат Ахин (СПбПУ) TO 2016 233 / 359
Средние оракулы
Хорошая точность
Средняя полнота
Марат Ахин (СПбПУ) TO 2016 234 / 359
Сильные оракулы
Эталонная реализация
Предыдущая версия программы
Формально верифицированная реализация
Автоматически сгенерированная версия
Марат Ахин (СПбПУ) TO 2016 235 / 359
Сильные оракулы
«Обратная функция»
Прямое/обратное преобразование Фурье
Архиватор/деархиватор
Кодер/декодер видео
Марат Ахин (СПбПУ) TO 2016 236 / 359
Сильные оракулы
Средняя точность
Хорошая полнота
Марат Ахин (СПбПУ) TO 2016 237 / 359
Генерация оракулов
Можно ли генерировать оракула автоматически?
Да!
Слабые оракулы
Средние оракулы
Марат Ахин (СПбПУ) TO 2016 238 / 359
Генерация оракулов
Можно ли генерировать оракула автоматически?
Да!
Слабые оракулы
Средние оракулы
Марат Ахин (СПбПУ) TO 2016 238 / 359
Генерация слабых оракулов
Все уже есть
Слабый оракул предоставляется средой выполнения
Если что-то упало, мы всегда об этом узнаем
Марат Ахин (СПбПУ) TO 2016 239 / 359
Генерация слабых оракулов
В явном виде используются весьма редко
Случайное тестирование
...
Сложно понять, где произошла ошибка
Не всегда очевидно, в чем именно заключается ошибка
Марат Ахин (СПбПУ) TO 2016 240 / 359
Генерация средних оракулов
Assertions
Тесты
Марат Ахин (СПбПУ) TO 2016 241 / 359
Генерация средних оракулов
Все уже есть
Средние оракулы разрабатываются параллельно с разработкой ПО
При возникновении проблемы мы сразу узнаем о ней
Зачем их генерировать автоматически?
Марат Ахин (СПбПУ) TO 2016 242 / 359
Генерация средних оракулов
Марат Ахин (СПбПУ) TO 2016 243 / 359
Генерация assertions
Assertions проверяют корректность внутреннего состояния
Как автоматически сгенерировать assertions?
Machine learning
Марат Ахин (СПбПУ) TO 2016 244 / 359
Генерация assertions
Собираем информацию о выполнении программы
Выводим определенные закономерности в работе программы
Генерируем assertion, проверяющий ненарушение закономерностей
...
PROFIT!
Хорошо работает для FSM-подобных программ
Плохо работает для всех остальных
Марат Ахин (СПбПУ) TO 2016 245 / 359
Генерация assertions
Собираем информацию о выполнении программы
В случае падения определяем его причину
Генерируем защитный assertion
...
PROFIT!
Способ усиления слабых оракулов до средних
Не работает, если ничего не падает
Марат Ахин (СПбПУ) TO 2016 246 / 359
Генерация тестов
Тесты – один из видов эталонной модели поведения
Как автоматически сгенерировать эталонную модель?
Мутационное тестирование
Марат Ахин (СПбПУ) TO 2016 247 / 359
Генерация тестов
Вспомним, что:
Идеальный тест работает только на тестируемой программе
Если тест проходит на мутанте, это плохо
Собираем информацию о выполнении оригинальной программы и
мутанта
Анализируем разницу
...
PROFIT!
Марат Ахин (СПбПУ) TO 2016 248 / 359
Генерация тестов для GUI
А если у нас есть GUI???
Что такое разница в работе GUI?
Как можно автоматически ее обнаружить?
Марат Ахин (СПбПУ) TO 2016 249 / 359
Генерация тестов для GUI
Нужна модель самого GUI
Нужна модель изменений GUI
Извлечение моделей должно выполняться автоматически
Марат Ахин (СПбПУ) TO 2016 250 / 359
Генерация тестов
Можно ли придумать что-то еще?
Случайное тестирование
Марат Ахин (СПбПУ) TO 2016 251 / 359
W.I.L.T.
Марат Ахин (СПбПУ) TO 2016 252 / 359
Случайное тестирование
Software Testing 101
Марат Ахин
Санкт-Петербургский политехнический университет
2016
Марат Ахин (СПбПУ) RT 2016 253 / 359
Quiz
Марат Ахин (СПбПУ) RT 2016 254 / 359
Recap
Марат Ахин (СПбПУ) RT 2016 255 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
6 Разработка через тестирование
7 Интеграционное тестирование
8 Проблема наблюдаемости
Марат Ахин (СПбПУ) RT 2016 256 / 359
Генерация тестов
Развитие идеи генерации тестовых оракулов
Полная автоматизация процесса тестирования
Марат Ахин (СПбПУ) RT 2016 257 / 359
Генерация тестов
Основная идея
Заставить компьютер работать вместо нас
Дешевле
Быстрее
Нет человеческого фактора
Марат Ахин (СПбПУ) RT 2016 258 / 359
Генерация тестов
Автоматическая генерация компонентов тестов
Входные данные
Последовательности вызовов API
Тестовые оракулы
Марат Ахин (СПбПУ) RT 2016 259 / 359
Генерация тестов
Результаты очень сильно зависят от того, что именно мы тестируем...
kd-tree
stoi
md5sum
PDF reader
Марат Ахин (СПбПУ) RT 2016 260 / 359
Fuzzing
Прародитель случайного тестирования
Полностью случайные данные
Вариант smoke testing
P8FT8PjBG7s71Bw1a8EP4svDPL5g4E791
TJcs5t9ZbxQAsLZx436PdJcxk3vq61192
Марат Ахин (СПбПУ) RT 2016 261 / 359
Fuzzing
Используем слабые оракулы
При необходимости вставляем заглушки
Что такое случайные данные?
Набор байт
Вызовы функций API
Пользовательский ввод
Марат Ахин (СПбПУ) RT 2016 262 / 359
Fuzzing
1989 – первое применение фаззинга на утилитах *NIX
1995 – повторная проверка утилит *NIX
2000 – проверка Windows NT/Windows 2000
2006 – проверка утилит Mac OS X
Стали ли результаты лучше?
Марат Ахин (СПбПУ) RT 2016 263 / 359
Fuzzing
Нет!
Все стало еще хуже!
GUI: 26% -> 45% -> 64% -> 73%
Многие баги, обнаруженные фаззингом, были исправлены...
...но появилось еще больше новых!
Марат Ахин (СПбПУ) RT 2016 264 / 359
Fuzzing
Марат Ахин (СПбПУ) RT 2016 265 / 359
Fuzzing
md5sum
kd-tree
stoi
PDF reader
Работает для всех программ
Но есть одно «но»... c
Марат Ахин (СПбПУ) RT 2016 266 / 359
Проблема валидности данных
Полностью случайные данные являются невалидными входными
данными для большинства программ
Марат Ахин (СПбПУ) RT 2016 267 / 359
Проблема валидности данных
Большинство программ ожидают структурированные входные
данные
P8FT8PjBG7s71Bw1a8EP4svDPL5g4E791
TJcs5t9ZbxQAsLZx436PdJcxk3vq61192
vs
3.1415926535897932384626433832797
[(1,0,0),(0,1,0),(0,0,1),(1,1,1)]
Марат Ахин (СПбПУ) RT 2016 268 / 359
Generative random testing
Если мы знаем структуру, то мы можем ей воспользоваться
Генерируем отдельные элементы
Комбинируем их в соответствии с заданной структурой
Вносим случайные нарушения структуры
Марат Ахин (СПбПУ) RT 2016 269 / 359
Generative random testing
Что такое структура?
Набор правил генерации
Грамматика
Формальная спецификация
Стандарт на формат входных файлов
Марат Ахин (СПбПУ) RT 2016 270 / 359
Generative random testing
kd-tree
stoi
PDF reader
Работает для структурированных входных данных
Но есть одно «но»... c
Марат Ахин (СПбПУ) RT 2016 271 / 359
Проблема сложной структуры
Иногда структура входных данных является слишком сложной
Марат Ахин (СПбПУ) RT 2016 272 / 359
Mutation random testing
Обычно у нас есть какой-то набор тестовых входных данных
Подвергаем тестовые данные мутации
При этом возможно использование знания структуры данных
Часть данных может генерироваться случайно
Марат Ахин (СПбПУ) RT 2016 273 / 359
Mutation random testing
Какие могут быть мутационные трансформации?
Добавление нового фрагмента
Удаление старого фрагмента
Изменение фрагмента
Обмен двух фрагментов местами
Замена значений на граничные
Марат Ахин (СПбПУ) RT 2016 274 / 359
Mutation random testing
PDF reader
Web browser
Работает практически для всего
Но есть одно «но»... c
Марат Ахин (СПбПУ) RT 2016 275 / 359
Проблема скелета в шкафу
Добраться до самых дальних закоулков нельзя
Марат Ахин (СПбПУ) RT 2016 276 / 359
Directed random testing
В чем заключаются основные проблемы случайного тестирования?
Некорректные тесты
Эквивалентные тесты
Длинные тесты
Марат Ахин (СПбПУ) RT 2016 277 / 359
Directed random testing
Марат Ахин (СПбПУ) RT 2016 278 / 359
Directed random testing
Некорректные тесты
Более строгие правила генерации/мутации
Явный учет некорректных тестов
Марат Ахин (СПбПУ) RT 2016 279 / 359
Directed random testing
Эквивалентные тесты
Обнаружение тестов, на которых программа ведет себя
одинаковым образом
Статически
Динамически
Вспомним про тестовое покрытие...
Марат Ахин (СПбПУ) RT 2016 280 / 359
Directed random testing
Длинные тесты
Минимизация тестов
Дихотомия
Стохастический поиск
Эволюционные алгоритмы
Delta debugging
Марат Ахин (СПбПУ) RT 2016 281 / 359
Directed random testing
А можно ли еще лучше?
Каждый новый тест минимально отличается от имеющихся
Каждый новый тест улучшает тестовое покрытие
Каждый новый тест должен генерироваться достаточно быстро
Марат Ахин (СПбПУ) RT 2016 282 / 359
Concolic testing
Concolic testing
Комбинируем информацию о конкретных выполнениях
программы...
...и информацию о символическом поведении программы
Комбинация статического и динамического анализов
Марат Ахин (СПбПУ) RT 2016 283 / 359
Satisfiability modulo theories
1 void f(int x) {
2 int y = x^2;
3
4 bool A = x > 0;
5 bool B = x < 10;
6 bool C = y > 20;
7
8 if (B && C) {
9 if (A) {
10 ...
11 }
12 }
13 }
SMT to the rescue
1 x, y = Ints(’x y’)
2 A, B, C = Bools(’A B C’)
3
4 s = Solver ()
5
6 s.add(y == x * x)
7 s.add(A == (x > 0))
8 s.add(B == (x < 10))
9 s.add(C == (y > 20))
Марат Ахин (СПбПУ) RT 2016 284 / 359
Satisfiability modulo theories
1 print s.check(B and C, A)
2 print s.model ()
3 # sat
4 # [A = True , B = True , y = 25, x = 5, C = True]
5
6 print s.check(B and C, Not(A))
7 print s.model ()
8 # sat
9 # [A = False , B = True , y = 25, x = -5, C = True]
10
11 print s.check(Not(B and C))
12 print s.model ()
13 # sat
14 # [A = False , B = True , y = 0, x = 0, C = False]
Марат Ахин (СПбПУ) RT 2016 285 / 359
Проблемы concolic testing
Почему я слышу об этом впервые в жизни?
Это сложно
Это очень сложно
Это очень-очень сложно
Марат Ахин (СПбПУ) RT 2016 286 / 359
Проблемы concolic testing
Инструментирование программы
Моделирование памяти
Взрыв пространства состояний
Оптимизации!
Марат Ахин (СПбПУ) RT 2016 287 / 359
Concolic testing
SAGE
Microsoft Research
500+ машино-лет
Более трети всех багов в различных проектах Microsoft
Развивается вместе с тестируемым им ПО
Марат Ахин (СПбПУ) RT 2016 288 / 359
Directed random testing
Visual Studio
Microsoft Office
Работает для всего
Но есть одно «но»... c
Марат Ахин (СПбПУ) RT 2016 289 / 359
Проблема мистера Икс
Некоторые части системы могут быть «черным ящиком»
Марат Ахин (СПбПУ) RT 2016 290 / 359
W.I.L.T.
Марат Ахин (СПбПУ) RT 2016 291 / 359
Регрессионное тестирование
Software Testing 101
Марат Ахин
Санкт-Петербургский политехнический университет
2016
Марат Ахин (СПбПУ) RT 2016 292 / 359
Quiz
Марат Ахин (СПбПУ) RT 2016 293 / 359
Recap
Марат Ахин (СПбПУ) RT 2016 294 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
6 Разработка через тестирование
7 Интеграционное тестирование
8 Проблема наблюдаемости
Марат Ахин (СПбПУ) RT 2016 295 / 359
Тестирование ПО в процессе разработки
Как ПО изменяется в процессе разработки?
Инкрементально, небольшими независимыми шагами
Изменение уже существующего кода
Исправление ошибок
Добавление новой функциональности
Адаптация имеющихся компонентов к новым задачам
Любые (даже самые незначительные) изменения могут серьезно
повлиять на качество ПО
Марат Ахин (СПбПУ) RT 2016 296 / 359
Тестирование ПО в процессе разработки
Как ПО изменяется в процессе разработки?
Инкрементально, небольшими независимыми шагами
Изменение уже существующего кода
Исправление ошибок
Добавление новой функциональности
Адаптация имеющихся компонентов к новым задачам
Любые (даже самые незначительные) изменения могут серьезно
повлиять на качество ПО
Марат Ахин (СПбПУ) RT 2016 296 / 359
Тестирование ПО в процессе разработки
Как ПО изменяется в процессе разработки?
Инкрементально, небольшими независимыми шагами
Изменение уже существующего кода
Исправление ошибок
Добавление новой функциональности
Адаптация имеющихся компонентов к новым задачам
Любые (даже самые незначительные) изменения могут серьезно
повлиять на качество ПО
Марат Ахин (СПбПУ) RT 2016 296 / 359
Тестирование ПО в процессе разработки
После любого изменения требуется проверить, что в программе не
появилось новых ошибок
Для этого мы выполняем все имеющиеся тесты и проверяем, что
все они успешно завершаются
Основной вид тестирования в процессе разработки ПО – это
регрессионное тестирование
Марат Ахин (СПбПУ) RT 2016 297 / 359
Регрессионное тестирование
Как выглядит одна итерация регрессионного тестирования?
1 Мы модифицируем программу P и получаем программу P
2 Из всего множества тестов T мы выбираем набор тестов T ,
который необходимо выполнить на P
3 Для новой функциональности мы разрабатываем новые тесты T
4 Полученный набор тестов T + T запускается на P
5 Результаты выполнения анализируются с последующей
возможной модификацией как программы, так и набора тестов
Какие проблемы связаны с РТ?
Марат Ахин (СПбПУ) RT 2016 298 / 359
Регрессионное тестирование
Проблема №1
Как выбрать набор тестов T после изменения в программе?
Консервативный подход
Выбираем все имеющиеся тесты
Полное регрессионное тестирование
Случайный подход
Выбираем случайное подмножество всех тестов
Случайное выборочное регрессионное тестирование
Марат Ахин (СПбПУ) RT 2016 299 / 359
Регрессионное тестирование
Каким свойствам должно удовлетворять выборочное регрессионное
тестирование?
Полнота – способность выбирать те тесты, которые могут
обнаружить ошибки, связанные с изменениями в коде
Точность – способность пропускать такие тесты, которые не
изменяют своего поведения на модифицированной программе
Эффективность – способность выполняться быстрее, чем полное
регрессионное тестирование
Универсальность – применимость в большинстве практических
ситуаций
«Качественно. Быстро. Дешево. Выберите любые два.»
Марат Ахин (СПбПУ) RT 2016 300 / 359
Регрессионное тестирование
Умный подход
Выбирать тесты, которые «затрагивают» при выполнении
измененные части программы
Выборочное регрессионное тестирование
Все подходы к ВРТ различаются по двум основным критериям
Способ идентификации измененных программных компонентов
Метод получения информации о покрытии элементов программы
тестами
Марат Ахин (СПбПУ) RT 2016 301 / 359
Подход МакКарти
Анализ изменений на уровне целого модуля
Связь элементов программы с тестами задается вручную
разработчиком
Преимущества и недостатки?
Марат Ахин (СПбПУ) RT 2016 302 / 359
Подход на основе концепции файервола
Анализ изменений на уровне целых модулей
Связь элементов программы с тестами задается вручную
разработчиком
Преимущества и недостатки?
Марат Ахин (СПбПУ) RT 2016 303 / 359
Подход Ротермела и Харролд
Анализ изменений на уровне узлов CFG программы
Связь элементов программы с тестами задается на уровне CFG на
основе динамической информации о выполнении каждого теста
Преимущества и недостатки?
Марат Ахин (СПбПУ) RT 2016 304 / 359
Подход Балла
Анализ изменений на уровне узлов CFG программы
Связь элементов программы с тестами задается на уровне CFG на
основе динамической информации о выполнении каждого теста
Преимущества и недостатки?
Марат Ахин (СПбПУ) RT 2016 305 / 359
Подход на основе AST
Анализ изменений на уровне вершин AST программы
Связь элементов программы с тестами задается на уровне AST на
основе динамической информации о выполнении каждого теста
Преимущества и недостатки?
Марат Ахин (СПбПУ) RT 2016 306 / 359
Управление регрессионными тестами
Проблема №2
Как управлять набором регрессионных тестов?
Когда и как добавлять в набор новые тесты?
Когда можно удалять старые тесты?
Марат Ахин (СПбПУ) RT 2016 307 / 359
Добавление новых тестов
Когда надо добавлять новый регрессионный тест?
Когда в ПО появилась новая функциональность
Когда в ПО была исправлена ошибка
Когда мы хотим улучшить тестовое покрытие ПО
Когда мы можем себе позволить добавить новый
неповторяющийся тест
Марат Ахин (СПбПУ) RT 2016 308 / 359
Добавление новых тестов
Когда надо добавлять новый регрессионный тест?
Когда в ПО появилась новая функциональность
Когда в ПО была исправлена ошибка
Когда мы хотим улучшить тестовое покрытие ПО
Когда мы можем себе позволить добавить новый
неповторяющийся тест
Марат Ахин (СПбПУ) RT 2016 308 / 359
Добавление новых тестов
Когда надо добавлять новый регрессионный тест?
Когда в ПО появилась новая функциональность
Когда в ПО была исправлена ошибка
Когда мы хотим улучшить тестовое покрытие ПО
Когда мы можем себе позволить добавить новый
неповторяющийся тест
Марат Ахин (СПбПУ) RT 2016 308 / 359
Добавление новых тестов
Когда надо добавлять новый регрессионный тест?
Когда в ПО появилась новая функциональность
Когда в ПО была исправлена ошибка
Когда мы хотим улучшить тестовое покрытие ПО
Когда мы можем себе позволить добавить новый
неповторяющийся тест
Марат Ахин (СПбПУ) RT 2016 308 / 359
Добавление новых тестов
С течением времени число тестов увеличивается
Чем больше тестов, тем лучше тестовое покрытие
Проблемы начинаются, когда тестов становится слишком много
Что такое «слишком много»?
Марат Ахин (СПбПУ) RT 2016 309 / 359
Удаление старых тестов
Когда можно удалять старый тест?
Никогда
Когда тест дублирует другие тесты
Когда тест не улучшает тестовое покрытие
Когда тест ни разу не обнаружил ошибки за все время
тестирования
Когда тест обнаруживает такие же ошибки, как и другие тесты
Марат Ахин (СПбПУ) RT 2016 310 / 359
Удаление старых тестов
Когда можно удалять старый тест?
Никогда
Когда тест дублирует другие тесты
Когда тест не улучшает тестовое покрытие
Когда тест ни разу не обнаружил ошибки за все время
тестирования
Когда тест обнаруживает такие же ошибки, как и другие тесты
Марат Ахин (СПбПУ) RT 2016 310 / 359
Удаление старых тестов
Когда можно удалять старый тест?
Никогда
Когда тест дублирует другие тесты
Когда тест не улучшает тестовое покрытие
Когда тест ни разу не обнаружил ошибки за все время
тестирования
Когда тест обнаруживает такие же ошибки, как и другие тесты
Марат Ахин (СПбПУ) RT 2016 310 / 359
Удаление старых тестов
Когда можно удалять старый тест?
Никогда
Когда тест дублирует другие тесты
Когда тест не улучшает тестовое покрытие
Когда тест ни разу не обнаружил ошибки за все время
тестирования
Когда тест обнаруживает такие же ошибки, как и другие тесты
Марат Ахин (СПбПУ) RT 2016 310 / 359
Удаление старых тестов
Когда можно удалять старый тест?
Никогда
Когда тест дублирует другие тесты
Когда тест не улучшает тестовое покрытие
Когда тест ни разу не обнаружил ошибки за все время
тестирования
Когда тест обнаруживает такие же ошибки, как и другие тесты
Марат Ахин (СПбПУ) RT 2016 310 / 359
Приоритизация регрессионных тестов
Проблема №3
Как запускать регрессионные тесты?
Взяли имеющийся набор тестов и запустили их
Такой подход может не всегда нас устраивать
Что мы можем изменить?
Марат Ахин (СПбПУ) RT 2016 311 / 359
Приоритизация регрессионных тестов
Мы можем изменить порядок, в котором мы запускаем
регрессионные тесты
Зачем?
Чем раньше мы узнаем о том, что в ПО появилась регрессионная
ошибка, тем скорее мы сможем приступить к ее исправлению
Часто причиной непрохождения различных (напрямую не
связанных друг с другом) тестов является одна и та же ошибка в
ПО
Иногда время на тестирование является ограниченным, и
необходимо найти наибольшее число ошибок с учетом всех
ограничений
Как мы можем приоритизировать регрессионные тесты?
Марат Ахин (СПбПУ) RT 2016 312 / 359
Приоритизация регрессионных тестов
При помощи интуиции
Подход работает, если у Вас хорошая интуиция
Кроме интуиции можно использовать имеющийся опыт разработки
ПО
Марат Ахин (СПбПУ) RT 2016 313 / 359
Приоритизация регрессионных тестов
На основе знаний о тестовом покрытии ПО
Сперва выполняются тесты, которые имеют наибольшее покрытие
ПО
Сперва выполняются тесты, которые покрывают более важные
компоненты ПО
Марат Ахин (СПбПУ) RT 2016 314 / 359
Приоритизация регрессионных тестов
На основе истории разработки
Приоритет отдается тестам, которые чаще других обнаруживали
регрессионные ошибки
Первыми выполняются тесты, проверяющие корректность работы
наиболее «проблемных» компонентов ПО
Марат Ахин (СПбПУ) RT 2016 315 / 359
Приоритизация регрессионных тестов
Случайным образом
Подход перекликается со случайным ВРТ
Если мы можем случайным образом поменять порядок
выполнения тестов, то почему бы это не сделать?
Марат Ахин (СПбПУ) RT 2016 316 / 359
Приоритизация регрессионных тестов
На основе характеристик тестов
Первыми выполняются тесты с наименьшим временем выполнения
Приоритет отдается тестам, которые наиболее активно работают с
окружением программной системы
Марат Ахин (СПбПУ) RT 2016 317 / 359
Анализ результатов регрессионного тестирования
Проблема №4
Что делать с результатами регрессионного тестирования?
Если все тесты проходят – все хорошо
Если тест не проходит – то все зависит от того, по какой причине
он не проходит
Варианты?
Марат Ахин (СПбПУ) RT 2016 318 / 359
Регрессионное тестирование на практике
Как обстоит дело с РТ/ВРТ на практике?
Марат Ахин (СПбПУ) RT 2016 319 / 359
Регрессионное тестирование на практике
РТ используется очень часто
TDD
Agile Development
RUP
ВРТ практически не используется
Почему?
Марат Ахин (СПбПУ) RT 2016 320 / 359
Регрессионное тестирование на практике
Крайняя сложность выбора регрессионных тестов
Опасность пропустить регрессионную ошибку при использовании
небезопасного ВРТ
Страх перед использованием «непонятной» технологии
Простота экстенсивного пути решения проблем РТ
Марат Ахин (СПбПУ) RT 2016 321 / 359
Регрессионное тестирование на практике
Отсутствие хорошей инструментальной поддержки
Test impact analysis
Chianti
Jimpa
...
Какие еще сложности связаны с ВРТ?
Марат Ахин (СПбПУ) RT 2016 322 / 359
Регрессионное тестирование на практике
Недетерминизм в тестах
Если выполнение тестов может отличаться от запуска к запуску —
все плохо
Почему?
Эффект «лавины»
Пропущенный тест в ВРТ может дальше привести к каскадному
пропуску множества тестов
Что делать?
Марат Ахин (СПбПУ) RT 2016 323 / 359
W.I.L.T.
Марат Ахин (СПбПУ) RT 2016 324 / 359
Дебаггинг
Software Testing 101
Марат Ахин
Санкт-Петербургский политехнический университет
2016
Марат Ахин (СПбПУ) DBG 2016 325 / 359
Quiz
Марат Ахин (СПбПУ) DBG 2016 326 / 359
Recap
Марат Ахин (СПбПУ) DBG 2016 327 / 359
Содержание
1 Прелюдия
2 Тестирование за 45 минут
3 Тестирование в процессе разработки ПО
4 Проблема тестовых входных данных
5 Проблема неявных входных данных
6 Разработка через тестирование
7 Интеграционное тестирование
8 Проблема наблюдаемости
Марат Ахин (СПбПУ) DBG 2016 328 / 359
Поиск ошибок
Debugging
Процесс поиска ошибок в программе
Edsger Dijkstra
If debugging is the process of removing bugs, then programming must be
the process of putting them in.
Марат Ахин (СПбПУ) DBG 2016 329 / 359
Поиск ошибок
Как найти ошибку?
Запустить тест
Тест выполнит фрагмент кода с ошибкой
Это вызовет порчу состояния программы
Результат работы программы будет некорректным
Марат Ахин (СПбПУ) DBG 2016 330 / 359
Поиск ошибок
Как найти ошибку?
Запустить тест
Тест выполнит фрагмент кода с ошибкой
Это вызовет порчу состояния программы
Результат работы программы будет некорректным
Марат Ахин (СПбПУ) DBG 2016 330 / 359
Поиск ошибок
Как найти ошибку?
Запустить тест
Тест выполнит фрагмент кода с ошибкой
Это вызовет порчу состояния программы
Результат работы программы будет некорректным
Марат Ахин (СПбПУ) DBG 2016 330 / 359
Поиск ошибок
Как найти ошибку?
Запустить тест
Тест выполнит фрагмент кода с ошибкой
Это вызовет порчу состояния программы
Результат работы программы будет некорректным
Марат Ахин (СПбПУ) DBG 2016 330 / 359
Поиск ошибок
Как найти ошибку?
Запустить тест
Тест выполнит фрагмент кода с ошибкой
Это вызовет порчу состояния программы
Результат работы программы будет некорректным
Марат Ахин (СПбПУ) DBG 2016 330 / 359
Поиск ошибок
Если мы решили проблему наблюдаемости...
Debugging не нужен
Assertions
Журнал выполнения
Если наблюдаемости не хватает???
Марат Ахин (СПбПУ) DBG 2016 331 / 359
Основная проблема
Основная проблема
Наблюдение за состоянием программы
Марат Ахин (СПбПУ) DBG 2016 332 / 359
Debuggers
Debugger to the rescue!
Две основные задачи отладчика
Пошаговое выполнение программы
Наблюдение за внутренним состоянием программы
Как они это делают?
Марат Ахин (СПбПУ) DBG 2016 333 / 359
Debuggers
Тесная интеграция со средой выполнения
Понимание того, что такое инструкция
Возможность останавливать выполнение в произвольные
моменты времени
Знание модели памяти
Способность модифицировать выполняемый код
...
Марат Ахин (СПбПУ) DBG 2016 334 / 359
Процесс отладки
Дубль №1
1 Выдвигаем гипотезу о месте возникновения ошибки
2 Настраиваем отладчик на анализ выбранного фрагмента кода
3 Запускаем программу на выполнение
4 Возможные варианты
1 Ошибка найдена
2 Гипотеза не подтвердилась
Если все же не нашли?
Марат Ахин (СПбПУ) DBG 2016 335 / 359
Процесс отладки
Дубль №2
1 Выдвигаем другую гипотезу о месте возникновения ошибки
2 Настраиваем отладчик на анализ выбранного фрагмента кода
3 Запускаем программу на выполнение
4 Возможные варианты
1 Ошибка найдена
2 Гипотеза не подтвердилась
Если все равно не нашли?
Марат Ахин (СПбПУ) DBG 2016 336 / 359
Процесс отладки
Дубль №3
1 Выдвигаем еще одну гипотезу о месте возникновения ошибки
2 Настраиваем отладчик на анализ выбранного фрагмента кода
3 Запускаем программу на выполнение
4 Возможные варианты
1 Ошибка найдена
2 Гипотеза не подтвердилась
А если...
Марат Ахин (СПбПУ) DBG 2016 337 / 359
Процесс отладки
Марат Ахин (СПбПУ) DBG 2016 338 / 359
Много ручного труда
Надо что-то с этим делать!
Марат Ахин (СПбПУ) DBG 2016 339 / 359
One step forward, two steps back...
Гипотезы обычно раскручиваются в обратном порядке
vs
Выполнение программы идет в прямом порядке
Марат Ахин (СПбПУ) DBG 2016 340 / 359
Step back
Марат Ахин (СПбПУ) DBG 2016 341 / 359
Time-traveling debugging
Отладка с возможностью выполнения программы в обратную сторону
Возможность детального исследования поведения программы
Нет необходимости перезапускать программу
Как это можно сделать?
Марат Ахин (СПбПУ) DBG 2016 342 / 359
Time-traveling debugging
Обратные функции
Трассировка
Запись состояния памяти (memory snapshots)
Не все так просто...
Марат Ахин (СПбПУ) DBG 2016 343 / 359
Неявные входные данные
Дата/время
Внешнее состояние (БД, сериализованные данные, и т.д.)
Работа с аппаратурой
Взаимодействие с другими программами
Чем больше неявных данных мы хотим учитывать, тем сложнее это
сделать эффективно
Марат Ахин (СПбПУ) DBG 2016 344 / 359
Time-traveling debugging
В самом плохом случае – полная запись всей трассы выполнения
Значение каждой переменной в каждый момент времени
Марат Ахин (СПбПУ) DBG 2016 345 / 359
Time-traveling virtual machine
Что еще можно сделать?
Все то же самое, но на уровне виртуальной машины
Запись взаимодействия ПО с аппаратурой
Возможность отладки целого ансамбля программ
Никаких проблем с неявными входными данными
Марат Ахин (СПбПУ) DBG 2016 346 / 359
Time-traveling virtual machine
Memory snapshots
Запись источников недетерминизма
Пользовательский ввод
Сетевое взаимодействие
Прерывания
TTVM позволяют отладить ошибки даже в ОС
Марат Ахин (СПбПУ) DBG 2016 347 / 359
Time travel
Марат Ахин (СПбПУ) DBG 2016 348 / 359
Дихотомия
Как поймать африканского льва?
Разделить Африку на две части стеной
Лев находится в одной из двух частей
Разделить часть со львом на две новой стеной
...
PROFIT!
Марат Ахин (СПбПУ) DBG 2016 349 / 359
Дихотомия в отладке
А можно ли то же самое сделать с тестом?
А можно ли это сделать автоматически?
Марат Ахин (СПбПУ) DBG 2016 350 / 359
Delta debugging
Способ автоматической минимизации теста
Дано: T = {Ci } : P(T) → fail
Найти: DD = min{Cj } ⊂ T : P(DD) → fail
Что такое Ci ?
Что такое min{Cj }?
Марат Ахин (СПбПУ) DBG 2016 351 / 359
Delta debugging
Ci – это...
Строка в файле
Вызов метода
Тэг в XML
Один байт данных
Коммит в VCS
Выбирается индивидуально в каждом конкретном случае
Марат Ахин (СПбПУ) DBG 2016 352 / 359
Delta debugging
DD = min{Cj } : ∀C ∈ DD P(DD  C) → pass
Удаление любого компонента из минимального теста приводит к
исчезновению ошибки
Чем меньше тест, тем проще его анализировать
Марат Ахин (СПбПУ) DBG 2016 353 / 359
Минимизация теста
Субоптимальный способ
Дихотомия
1: function DD(CC)
2: L = {CC1, . . . , CC|CC|/2}
3: R = {CC|CC|/2+1, . . . , CC|CC|}
4: if only P(L) → fail then
5: return DD(L)
6: else if only P(R) → fail then
7: return DD(R)
8: else
9: return CC
10: end if
11: end function
Марат Ахин (СПбПУ) DBG 2016 354 / 359
Минимизация теста
«Оптимальный» способ
Полный перебор
1: function DD(CC)
2: CC = CC  {CCi }
3: if P(CC ) → fail then
4: return DD(CC )
5: else if P(CC ) → pass then
6: return CCi ∪ DD(CC )
7: end if
8: end function
Марат Ахин (СПбПУ) DBG 2016 355 / 359
Минимизация теста
Оптимальный способ
Умный перебор
1: function DD(CC, N)
2: CC = CC1 ∪ . . . ∪ CCN
3: for all CCi do
4: if P(CCi ) → fail then
5: return DD(CCi )
6: else if P(CC  CCi ) → fail then
7: return DD(CC  CCi )
8: end if
9: end for
10: return DD(CC, 2 × N)
11: end function
Марат Ахин (СПбПУ) DBG 2016 356 / 359
Delta debugging на практике
Готовых средств для delta debugging над данными нет
Зависимость Ci от типа данных
Разные проекты могут накладывать дополнительные ограничения
git/hg bisect
Марат Ахин (СПбПУ) DBG 2016 357 / 359
W.I.L.T.
Марат Ахин (СПбПУ) DBG 2016 358 / 359
Q&A
Марат Ахин (СПбПУ) DBG 2016 359 / 359

Тестирование ПО (2016)

  • 1.
    Tестирование программного обеспечения Что,зачем и почему? Software Testing 101 Марат Ахин Санкт-Петербургский политехнический университет 2016 Марат Ахин (СПбПУ) Intro 2016 1 / 359
  • 2.
    Содержание 1 Прелюдия Обеспечение качестваПО Тестирование ПО 2 Тестирование за 45 минут 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных 6 Разработка через тестирование 7 Интеграционное тестирование Марат Ахин (СПбПУ) Intro 2016 2 / 359
  • 3.
    Обеспечение качества ПО Функциональныеvs нефункциональные требования Марат Ахин (СПбПУ) Intro 2016 3 / 359
  • 4.
    Обеспечение качества ПО Функциональныетребования Адекватность Точность Интероперабельность Безопасность Нефункциональные требования Надежность Эффективность Поддерживаемость Переносимость Как можно их проверять? Марат Ахин (СПбПУ) Intro 2016 4 / 359
  • 5.
    Обеспечение качества ПО МаратАхин (СПбПУ) Intro 2016 5 / 359
  • 6.
    Обеспечение качества ПО Thinkingis hard, running is simple. (c) Запустить программу просто и это можно сделать всегда Думать о программе сложно и требует «высшего знания» Будем запускать программу, чтобы проверить, отвечает ли она предъявленным требованиям Марат Ахин (СПбПУ) Intro 2016 6 / 359
  • 7.
    Что такое тестированиеПО? То, чем вы будете заниматься до 80% времени Марат Ахин (СПбПУ) Intro 2016 7 / 359
  • 8.
    Что за вопрослежит в основе тестирования? Работает ли это ПО правильно? НЕТ Работает ли это ПО неправильно? ДА Тестирование = Разрушение Марат Ахин (СПбПУ) Intro 2016 8 / 359
  • 9.
    Что за вопрослежит в основе тестирования? Работает ли это ПО правильно? НЕТ Работает ли это ПО неправильно? ДА Тестирование = Разрушение Марат Ахин (СПбПУ) Intro 2016 8 / 359
  • 10.
    Что за вопрослежит в основе тестирования? Работает ли это ПО правильно? НЕТ Работает ли это ПО неправильно? ДА Тестирование = Разрушение Марат Ахин (СПбПУ) Intro 2016 8 / 359
  • 11.
    Что за вопрослежит в основе тестирования? Работает ли это ПО правильно? НЕТ Работает ли это ПО неправильно? ДА Тестирование = Разрушение Марат Ахин (СПбПУ) Intro 2016 8 / 359
  • 12.
    Что за вопрослежит в основе тестирования? Работает ли это ПО правильно? НЕТ Работает ли это ПО неправильно? ДА Тестирование = Разрушение Марат Ахин (СПбПУ) Intro 2016 8 / 359
  • 13.
    Кому помогает тестирование? Лучшийдруг верификации и валидации ПО В чем разница? Верификация – «мы сделали это правильно» Валидация – «мы сделали то, что надо» Марат Ахин (СПбПУ) Intro 2016 9 / 359
  • 14.
    Можем ли мычто-то гарантировать при тестировании? Данное ПО никогда не упадет Потоки никогда не заблокируются Вычисления всегда выполняются корректно Временные характеристики всегда выдерживаются Мы можем дать такие гарантии лишь в самых тривиальных случаях, когда обычно все ясно и без тестирования Марат Ахин (СПбПУ) Intro 2016 10 / 359
  • 15.
    Можем ли мычто-то гарантировать при тестировании? Данное ПО никогда не упадет Потоки никогда не заблокируются Вычисления всегда выполняются корректно Временные характеристики всегда выдерживаются Мы можем дать такие гарантии лишь в самых тривиальных случаях, когда обычно все ясно и без тестирования Марат Ахин (СПбПУ) Intro 2016 10 / 359
  • 16.
    Почему тестировать сложно? BrianKernighan «Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.» Massimo Arnoldi (feat. Kent Beck) «Unfortunately at least for me (and not only) testing goes against human nature. If you realize the pig in you, you will see that you program without tests.» Марат Ахин (СПбПУ) Intro 2016 11 / 359
  • 17.
    Почему тестировать нужно? Еслиотложить сегодняшние дела на послезавтра, у вас появятся два свободных дня! (с) Марат Ахин (СПбПУ) Intro 2016 12 / 359
  • 18.
    Что же делать? МаратАхин (СПбПУ) Intro 2016 13 / 359
  • 19.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут Тестирование ПО с точки зрения дилетанта Модель программной ошибки Модель тестирования ПО Процесс тестирования ПО 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных 6 Разработка через тестирование 7 Интеграционное тестированиеМарат Ахин (СПбПУ) Intro 2016 14 / 359
  • 20.
    Тестирование ПО сточки зрения дилетанта Запустили приложение Проверили результаты выполнения на предмет наличия в них ошибок aka «багов» aka «сбоев» aka «дефектов» aka «неудач» Сперва надо разобраться, а что же такое «программная ошибка»? Марат Ахин (СПбПУ) Intro 2016 15 / 359
  • 21.
    Модель программной ошибки FAILURE FAULT ERROR Неудача– наблюдаемое снаружи некорректное поведение программы Сбой – некорректное состояние программы из-за ошибки Ошибка – ошибка в самой программе, внесенная на этапе разработки Рассмотрим данную модель на примере Марат Ахин (СПбПУ) Intro 2016 16 / 359
  • 22.
    Модель программной ошибки Найдитеошибку в следующей программе на Java 1 int sumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Возможное переполнение в строке 4 Марат Ахин (СПбПУ) Intro 2016 17 / 359
  • 23.
    Модель программной ошибки Найдитеошибку в следующей программе на Java 1 int sumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Возможное переполнение в строке 4 Марат Ахин (СПбПУ) Intro 2016 17 / 359
  • 24.
    Модель программной ошибки c= {} Что будет? 1 int sumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Нет ни сбоя, ни неудачи – программа работает корректно Марат Ахин (СПбПУ) Intro 2016 18 / 359
  • 25.
    Модель программной ошибки c= {} Что будет? 1 int sumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Нет ни сбоя, ни неудачи – программа работает корректно Марат Ахин (СПбПУ) Intro 2016 18 / 359
  • 26.
    Модель программной ошибки c= {1, 2, 3, 5} Что будет? 1 int sumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Нет ни сбоя, ни неудачи – программа работает корректно Марат Ахин (СПбПУ) Intro 2016 19 / 359
  • 27.
    Модель программной ошибки c= {1, 2, 3, 5} Что будет? 1 int sumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Нет ни сбоя, ни неудачи – программа работает корректно Марат Ахин (СПбПУ) Intro 2016 19 / 359
  • 28.
    Модель программной ошибки c= {1, 2, 3, 5, Integer.MAX_VALUE, Integer.MIN_VALUE} Что будет? 1 int sumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Сбой есть – программа проходит через некорректное состояние Но неудачи нет – результат работы программы корректен Марат Ахин (СПбПУ) Intro 2016 20 / 359
  • 29.
    Модель программной ошибки c= {1, 2, 3, 5, Integer.MAX_VALUE, Integer.MIN_VALUE} Что будет? 1 int sumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Сбой есть – программа проходит через некорректное состояние Но неудачи нет – результат работы программы корректен Марат Ахин (СПбПУ) Intro 2016 20 / 359
  • 30.
    Модель программной ошибки c= {1, 2, 3, 5, Integer.MAX_VALUE} Что будет? 1 int sumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Сбой есть – программа проходит через некорректное состояние Неудача тоже есть – результат работы программы неправильный Марат Ахин (СПбПУ) Intro 2016 21 / 359
  • 31.
    Модель программной ошибки c= {1, 2, 3, 5, Integer.MAX_VALUE} Что будет? 1 int sumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Сбой есть – программа проходит через некорректное состояние Неудача тоже есть – результат работы программы неправильный Марат Ахин (СПбПУ) Intro 2016 21 / 359
  • 32.
    Что мы делали? ЗапускалиПО (мысленно) Сравнивали результаты работы с ожидаемыми (логически) Можно ли придумать другой способ тестирования? Марат Ахин (СПбПУ) Intro 2016 22 / 359
  • 33.
    Модель тестирования ПО Эталоннаямодель может быть представлена множеством различных способов неформальное представление о том, «как должна работать программа» формальная техническая спецификация набор тестовых примеров корректные результаты работы программы другая (априори корректная) реализация той же исходной спецификации Марат Ахин (СПбПУ) Intro 2016 23 / 359
  • 34.
    Процесс тестирования ПО Чтоможет случиться? Марат Ахин (СПбПУ) Intro 2016 24 / 359
  • 35.
  • 36.
    Тест не прошел OH-MI-GOD! МаратАхин (СПбПУ) Intro 2016 26 / 359
  • 37.
    Ошибка в ПО Всепросто и понятно, да? Марат Ахин (СПбПУ) Intro 2016 27 / 359
  • 38.
    Ошибка в эталонноймодели Некорректный тест? Ошибка в спецификации? Марат Ахин (СПбПУ) Intro 2016 28 / 359
  • 39.
    Ошибка в тестовомокружении Баг в тестовой библиотеке? Марат Ахин (СПбПУ) Intro 2016 29 / 359
  • 40.
    Ошибка в платформе Багв ОС? Аппаратный сбой? Ошибка компилятора? Марат Ахин (СПбПУ) Intro 2016 30 / 359
  • 41.
    Процесс тестирования ПО Являетсяли данная модель самодостаточной? Марат Ахин (СПбПУ) Intro 2016 31 / 359
  • 42.
    Процесс тестирования ПО Откудабрать эталонную модель? Как сравнивать результаты работы программы и модели? Марат Ахин (СПбПУ) Intro 2016 32 / 359
  • 43.
    Процесс тестирования ПО Когдаостанавливать процесс тестирования? Марат Ахин (СПбПУ) Intro 2016 33 / 359
  • 44.
    Процесс тестирования ПО Какподобрать входные данные, чтобы: дойти до места с программной ошибкой (Reachibility) испортить состояние программы с появлением сбоя (Corruption) вызвать неудачу в работе программы (Propagation) Марат Ахин (СПбПУ) Intro 2016 34 / 359
  • 45.
    Проблемы тестирования What’s up,Doc? (с) Проблема тестовых входных данных Проблема наблюдаемости Проблема «останова» Проблема тестового оракула Марат Ахин (СПбПУ) Intro 2016 35 / 359
  • 46.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут 3 Тестирование в процессе разработки ПО Модели разработки ПО Проблемы тестирования ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных 6 Разработка через тестирование 7 Интеграционное тестирование Марат Ахин (СПбПУ) Intro 2016 36 / 359
  • 47.
    Модели разработки ПО Чемактивнее используется тестирование в процессе разработки, тем важнее его правильное использование Марат Ахин (СПбПУ) Intro 2016 37 / 359
  • 48.
    Водопадная модель Строго последовательнаямодель разработки Тестирование выполняется над всей программой сразу Имеется хорошая эталонная модель Стоимость поиска и исправления ошибок очень высока Марат Ахин (СПбПУ) Intro 2016 38 / 359
  • 49.
    Инкрементальная модель Разработка проходитв несколько итераций Тестируются отдельные версии программы Имеется неплохая эталонная модель Стоимость поиска и исправления ошибок высока Марат Ахин (СПбПУ) Intro 2016 39 / 359
  • 50.
    Гибкая модель Все этапыразработки неразрывно связаны друг с другом Тестированию подвергаются как сама программа, так и ее компоненты Эталонная модель есть не всегда Стоимость поиска и исправления ошибок относительно низка Марат Ахин (СПбПУ) Intro 2016 40 / 359
  • 51.
    Проблемы тестирования ПО Развечто-то может пойти совсем плохо? Марат Ахин (СПбПУ) Intro 2016 41 / 359
  • 52.
    Розовые очки Марат Ахин(СПбПУ) Intro 2016 42 / 359
  • 53.
    Розовые очки Неправильное тестированиесоздает иллюзию, что все хорошо... ...тогда как на самом деле все может быть очень и очень плохо Все тесты проходят Выпускаем код в релиз ... BOOM! Марат Ахин (СПбПУ) Intro 2016 43 / 359
  • 54.
  • 55.
    Наводнение Неправильное тестирование создаетиллюзию, что все плохо... ...тогда как на самом деле все вполне себе ничего Большинство тестов не проходит Садимся и исправляем ошибки ... UNREACHABLE! Марат Ахин (СПбПУ) Intro 2016 45 / 359
  • 56.
  • 57.
    Прятки Неправильное тестирование создаетиллюзию, что все плохо... ...тогда как на самом деле все плохо в другом месте Некоторые тесты не проходит Садимся и ищем ошибки ... HUH? Марат Ахин (СПбПУ) Intro 2016 47 / 359
  • 58.
    Что же делать? МаратАхин (СПбПУ) Intro 2016 48 / 359
  • 59.
    Что же делать? МаратАхин (СПбПУ) Intro 2016 49 / 359
  • 60.
  • 61.
    Проблема тестовых входныхданных Software Testing 101 Марат Ахин Санкт-Петербургский политехнический университет 2016 Марат Ахин (СПбПУ) Input 2016 51 / 359
  • 62.
  • 63.
  • 64.
    Проблемы тестирования What’s up,Doc? (с) Проблема тестовых входных данных Проблема наблюдаемости Проблема «останова» Проблема тестового оракула Марат Ахин (СПбПУ) Input 2016 54 / 359
  • 65.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных Обеспечение достижимости Входные данные Тестовые данные Классы эквивалентности 5 Проблема неявных входных данных 6 Разработка через тестирование 7 Интеграционное тестированиеМарат Ахин (СПбПУ) Input 2016 55 / 359
  • 66.
    Обеспечение достижимости Какими способамиможно управлять выполнением кода? Изменением входных данных Изменением самого исходного кода Какой способ можно использовать для обеспечения достижимости (reachability)? Марат Ахин (СПбПУ) Input 2016 56 / 359
  • 67.
    Обеспечение достижимости Какими способамиможно управлять выполнением кода? Изменением входных данных Изменением самого исходного кода Какой способ можно использовать для обеспечения достижимости (reachability)? Марат Ахин (СПбПУ) Input 2016 56 / 359
  • 68.
    Обеспечение достижимости Какими способамиможно управлять выполнением кода? Изменением входных данных Изменением самого исходного кода Какой способ можно использовать для обеспечения достижимости (reachability)? Марат Ахин (СПбПУ) Input 2016 56 / 359
  • 69.
    Обеспечение достижимости Какими способамиможно управлять выполнением кода? Изменением входных данных Изменением самого исходного кода Какой способ можно использовать для обеспечения достижимости (reachability)? Марат Ахин (СПбПУ) Input 2016 56 / 359
  • 70.
    Входные данные Что такоевходные данные? Марат Ахин (СПбПУ) Input 2016 57 / 359
  • 71.
    Входные данные Файлы Фактические аргументыфункций Сетевые пакеты Результаты запроса к БД Последовательность вызовов функций Конфигурация ПО Марат Ахин (СПбПУ) Input 2016 58 / 359
  • 72.
    Тестовые данные Почему быпросто не перебрать все возможные варианты? 1 int add(int a, int b) { ... } 18,446,744,073,709,551,616 вариантов А если у тестируемого модуля есть внутреннее состояние? Марат Ахин (СПбПУ) Input 2016 59 / 359
  • 73.
    Тестовые данные Марат Ахин(СПбПУ) Input 2016 60 / 359
  • 74.
    Классы эквивалентности Все пространствовходных состояний можно разбить на множество классов эквивалентности Каждый класс эквивалентности обрабатывается тестируемым модулем одинаково с точки зрения спецификации Тестирование всех классов эквивалентности позволяет найти ошибки прямого нарушения спецификации Как найти классы эквивалентности? Марат Ахин (СПбПУ) Input 2016 61 / 359
  • 75.
    Ad hoc testing Тестированиеметодом «научного тыка» Запускаем ПО Смотрим на результаты работы ... PROFIT! Марат Ахин (СПбПУ) Input 2016 62 / 359
  • 76.
    Ad hoc testing Ачто будет, если я нажму на эту кнопочку? Если сложить два положительных числа, то... После умножения на ноль в результате должен получится ноль Если ввести очень большое число и удвоить его, то... В чем проблемы при таком подходе к тестированию? Марат Ахин (СПбПУ) Input 2016 63 / 359
  • 77.
    Метод свободного поиска Adhoc testing + планирование Описываем тест-план Проверяем ПО на соответствие тест-плану ... PROFIT! Марат Ахин (СПбПУ) Input 2016 64 / 359
  • 78.
    Метод свободного поиска Есливвести число «42», потом нажать «+», потом ввести «1» и нажать «=», в результате должно получиться «43» Многократные нажатия на «C» не должны приводить к видимым изменениям в интерфейсе В чем проблемы при таком подходе к тестированию? Марат Ахин (СПбПУ) Input 2016 65 / 359
  • 79.
    Анализ граничных значений Баюбаюшки баю, не ложися на краю... Находим пограничные значения входных данных Проверяем ПО вокруг выбранных пограничных значений ... PROFIT! Марат Ахин (СПбПУ) Input 2016 66 / 359
  • 80.
    Анализ граничных значений Еслиумножить любое число на «0», должен получиться «0» Деление любого числа на «0» должно приводить к выводу соответствующей ошибки Если изменить знак наибольшего представимого положительного числа, должно получиться соответствующее ему отрицательное число В чем проблемы при таком подходе к тестированию? Марат Ахин (СПбПУ) Input 2016 67 / 359
  • 81.
  • 82.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных Неявные входные данные Использование заглушек 6 Разработка через тестирование 7 Интеграционное тестирование Марат Ахин (СПбПУ) Input 2016 69 / 359
  • 83.
    Неявные входные данные Покрываетли спецификация все множество входных данных? В некоторых случаях – да В большинстве случаев – нет Почему? Проблема заключается в том, что на тестовый модуль, кроме явных, влияет множество неявных входных данных Неявные входные данные часто не находят отражения в спецификации Марат Ахин (СПбПУ) Input 2016 70 / 359
  • 84.
    Неявные входные данные Текущаядата/время IP/MAC адрес Локаль пользователя Идентификаторы устройств Контекстные переключения/планирование нитей Скорость поступления IP пакетов Ритм нажатия клавиш на клавиатуре Все это – примеры неявных входных данных Марат Ахин (СПбПУ) Input 2016 71 / 359
  • 85.
  • 86.
    Robot pharmacist Марат Ахин(СПбПУ) Input 2016 73 / 359
  • 87.
    Как учесть неявныевходные данные? Какими способами можно управлять выполнением кода? Изменением входных данных Изменением самого исходного кода Simulate and Stub Заменяем части модуля управляемыми заглушками Это позволяет сделать неявные входные данные явными Это также делает управление явными входными данными проще Марат Ахин (СПбПУ) Input 2016 74 / 359
  • 88.
    Использование заглушек Данный подходпозволяет: имитировать возникновение редких ситуаций внести детерминизм там, где его нет Для того, чтобы можно было использовать S&S, тестируемый модуль должен разрабатываться соответствующим образом Марат Ахин (СПбПУ) Input 2016 75 / 359
  • 89.
    Mock-объекты Пример S&S –mock-объекты Повторяют внешний интерфейс тестируемого объекта Могут демонстрировать любое требуемое поведение Марат Ахин (СПбПУ) Input 2016 76 / 359
  • 90.
    Mockito 1 @Test 2 voidtestFoo () { 3 List mockedList = mock(List.class ); 4 5 when(mockedList.get (0)). thenReturn("first"); 6 when(mockedList.get (1)). thenReturn("second"); 7 8 assertEquals ("first", mockedList.get (0)); 9 assertEquals ("second", mockedList.get (1)); 10 assertEquals (null , mockedList.get (42)); 11 } Марат Ахин (СПбПУ) Input 2016 77 / 359
  • 91.
    Mockito Сервис аутентификации иавторизации Вход пользователя с корректными логином/паролем должен приводить к переходу его учетной записи в активное состояние Марат Ахин (СПбПУ) Input 2016 78 / 359
  • 92.
    Mockito 1 @Test 2 voidtestLoginForValidUser () { 3 IPasswordInfo passInfo = mock( IPasswordInfo .class ); 4 when(passInfo.matches(anyString ())). thenReturn(true ); 5 6 IAccount account = mock(IAccount.class ); 7 when(account. getPasswordInfo ()). thenReturn(passInfo ); 8 9 IAccountRepository repo = mock( IAccountRepository .class ); 10 when(repo.find(anyString (), anyString ())). thenReturn(account ); 11 12 AuthService service = new AuthService(repo ); 13 service.login("marat", "password2"); 14 15 verify(account ). setLoggedIn (true ); 16 } Марат Ахин (СПбПУ) Input 2016 79 / 359
  • 93.
    Mockito Сервис аутентификации иавторизации Три последовательные попытки входа пользователя с некорректным паролем должны приводить к блокированию его учетной записи Марат Ахин (СПбПУ) Input 2016 80 / 359
  • 94.
    Mockito 1 @Test 2 voidtestBlockOnIncorrectLogin () { 3 IPasswordInfo passInfo = mock( IPasswordInfo .class ); 4 when(passInfo.matches(anyString ())). thenReturn(false ); 5 6 IAccount account = mock(IAccount.class ); 7 when(account. getPasswordInfo ()). thenReturn(passInfo ); 8 9 IAccountRepository repo = mock( IAccountRepository .class ); 10 when(repo.find(anyString (), anyString ())). thenReturn(account ); 11 12 AuthService service = new AuthService(repo ); 13 service.login("bob", "111"); 14 service.login("bob", "123"); 15 service.login("bob", "321"); 16 17 verify(account ). setBlocked(true ); 18 } Марат Ахин (СПбПУ) Input 2016 81 / 359
  • 95.
    Mockito 1 @Test 2 voidtestBlockOnIncorrectLoginPerAccount () { 3 IPasswordInfo aliceInfo = getMockedPasswordInfo (false ); 4 IPasswordInfo bobInfo = getMockedPasswordInfo (false ); 5 6 IAccount aliceAcc = getMockedAccount (aliceInfo ); 7 IAccount bobAcc = getMockedAccount (bobInfo ); 8 9 IAccountRepository repo = mock( IAccountRepository .class ); 10 when(repo.find("alice", anyString ())). thenReturn(aliceAcc ); 11 when(repo.find("bob", anyString ())). thenReturn(bobAcc ); 12 13 AuthService service = new AuthService(repo ); 14 service.login("bob", "111"); 15 service.login("alice", "111"); 16 service.login("bob", "123"); 17 service.login("alice", "123"); 18 service.login("bob", "321"); 19 20 verify(aliceAcc , never ()). setBlocked(true ); 21 verify(bobAcc , times (1)). setBlocked(true ); 22 } Марат Ахин (СПбПУ) Input 2016 82 / 359
  • 96.
    Mocks = Stubs= Fakes = Dummies Разве есть разница? Dummies Объект-муляж, не обладающий собственным поведением Fakes Упрощенная реализация требуемой функциональности Stubs Тестовая заглушка, способная отвечать на внешние запросы Mocks Тестовая загрушка, способная отвечать на внешние запросы и проверять их корректность Марат Ахин (СПбПУ) Input 2016 83 / 359
  • 97.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных 6 Разработка через тестирование Test-driven development Плюсы TDD Минусы TDD 7 Интеграционное тестирование Марат Ахин (СПбПУ) Input 2016 84 / 359
  • 98.
    Нужны ли заглушки? Акак использовать mock-объекты в процессе разработки? Для управления неявными входными данными Для управления явными входными данными А когда их следует использовать? Марат Ахин (СПбПУ) Input 2016 85 / 359
  • 99.
    Заглушки не нужны? Никогда! Зачемтратить время на разработку и использование заглушек? Можно просто подождать, пока не будут разработаны все компоненты Получится проще, дешевле и лучше, чем с заглушками! Марат Ахин (СПбПУ) Input 2016 86 / 359
  • 100.
    Заглушки не нужны? Всеже будет хорошо, да? Марат Ахин (СПбПУ) Input 2016 87 / 359
  • 101.
    Заглушки нужны? Чем дольшеитерация, тем сложнее и дороже исправление ошибок Чем быстрее будут написаны тесты для разрабатываемого компонента, тем проще найти ошибки После разработки компонента пишем для него тест Отсутствующие части системы заменяем заглушками ... PROFIT! Марат Ахин (СПбПУ) Input 2016 88 / 359
  • 102.
    Заглушки нужны? А давайтеписать тесты еще быстрее? Марат Ахин (СПбПУ) Input 2016 89 / 359
  • 103.
    Test-driven development Пишем тестдля компонента перед его разработкой Заменяем сам компонент заглушкой ... PROFIT??? Разве это будет работать? Марат Ахин (СПбПУ) Input 2016 90 / 359
  • 104.
    Test-driven development Разве этобудет работать? Марат Ахин (СПбПУ) Input 2016 91 / 359
  • 105.
    Плюсы TDD Разработка ведетсянебольшими контролируемыми фрагментами В каждый момент времени разработчик думает об ограниченном фрагменте спецификации Это упрощает анализ возможного пространства входных данных Кроме того, код получается более модульным и расширяемым Марат Ахин (СПбПУ) Input 2016 92 / 359
  • 106.
    Плюсы TDD Минимальная ценаошибки В случае возникновения ошибки очень просто вернуть систему в рабочее состояние Практически отсутствует необходимость в отладке Крайне просто использовать метод бисекции в случае, если ошибка смогла пробраться в релиз Марат Ахин (СПбПУ) Input 2016 93 / 359
  • 107.
    Плюсы TDD Ошибки обнаруживаютсясразу же после их появления Постоянный запуск тестов гарантирует практически моментальное обнаружение ошибки Малый размер тестов позволяет быстро найти причину ошибки Марат Ахин (СПбПУ) Input 2016 94 / 359
  • 108.
    Плюсы TDD Сильно упрощаетсярефакторинг кода Программист уверен в том, что его изменения ничего не ломают Облегчается раздельное владение кодом Марат Ахин (СПбПУ) Input 2016 95 / 359
  • 109.
    Почему я слышуо TDD впервые в жизни? Почему TDD не используют везде и всюду?! Марат Ахин (СПбПУ) Input 2016 96 / 359
  • 110.
    Минусы TDD Синдром «розовыхочков» Большое количество тестов создает иллюзию бесконечной надежности системы тестирования При создании теста разработчик может сделать те же допущения, что и при разработке самого компонента Марат Ахин (СПбПУ) Input 2016 97 / 359
  • 111.
    Минусы TDD Поддержание тестовв актуальном состоянии При внесении изменений в интерфейсы компонентов системы необходимо соответствующим образом изменить и все тесты Большое количество тестов приводит к значительным затратам на рефакторинг тестов Марат Ахин (СПбПУ) Input 2016 98 / 359
  • 112.
    Минусы TDD Невозможность тестированиясложного взаимодействия нескольких компонентов Каждый тест проверяет ограниченный фрагмент функциональности системы Взаимодействие компонентов затрагивает множество аспектов системы сразу Марат Ахин (СПбПУ) Input 2016 99 / 359
  • 113.
    Стоит ли использоватьTDD? Марат Ахин (СПбПУ) Input 2016 100 / 359
  • 114.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных 6 Разработка через тестирование 7 Интеграционное тестирование Проблема «Большого Взрыва» Нисходящее интеграционное тестирование Восходящее интеграционное тестирование Марат Ахин (СПбПУ) Input 2016 101 / 359
  • 115.
    Проблема «Большого Взрыва» Когдаприходит время заменять заглушки на реализацию... Марат Ахин (СПбПУ) Input 2016 102 / 359
  • 116.
    Проблема «Большого Взрыва» Поведениереализации может (и скорее всего будет) отличаться от поведения заглушки Если заглушек было много... Марат Ахин (СПбПУ) Input 2016 103 / 359
  • 117.
    Проблема «Большого Взрыва» Каскадноераспространение сбоев Сложность локализации ошибок Большая стоимость исправления ошибок Что мы можем сделать? Марат Ахин (СПбПУ) Input 2016 104 / 359
  • 118.
    Интеграционное тестирование Ускорить процессзамены заглушек на реализацию Выполнять тестирование взаимодействия постоянно, в процессе разработки Заменять заглушки на реализацию инкрементально Инкрементальное интеграционное тестирование Марат Ахин (СПбПУ) Input 2016 105 / 359
  • 119.
  • 120.
    Нисходящее интеграционное тестирование Тестированиеначинается с верхних уровней системы Отсутствующие на данный момент модули заменяются «заглушками» По мере реализации новых модулей они подключаются к системе вместо «заглушек» Марат Ахин (СПбПУ) Input 2016 107 / 359
  • 121.
    Нисходящее интеграционное тестирование Преимущества Возможностьранней проверки корректности высокоуровневого поведения Модули могут добавляться по одному, независимо друг от друга Не требуется разработка множества драйверов Можно разрабатывать систему как в глубину, так и в ширину Марат Ахин (СПбПУ) Input 2016 108 / 359
  • 122.
    Нисходящее интеграционное тестирование Недостатки Отложеннаяпроверка низкоуровневого поведения Требуется разработка «заглушек» Крайне сложно корректно сформулировать требования ко входам/выходам частичной системы Марат Ахин (СПбПУ) Input 2016 109 / 359
  • 123.
    Восходящее интеграционное тестирование Тестированиеначинается с нижних уровней системы Отсутствующие на данный момент модули заменяются драйверами При реализации всех модулей нижнего уровня драйвер может быть заменен на соответствующий модуль Марат Ахин (СПбПУ) Input 2016 110 / 359
  • 124.
    Восходящее интеграционное тестирование Преимущества Возможностьранней проверки корректности низкоуровневого поведения Не требуется написание заглушек Просто определить требования ко входам/выходам модулей Марат Ахин (СПбПУ) Input 2016 111 / 359
  • 125.
    Восходящее интеграционное тестирование Недостатки Отложеннаяпроверка высокоуровневого поведения Требуется разработка драйверов При замене драйвера на модуль высокого уровня может произойти «мини-Большой Взрыв» Марат Ахин (СПбПУ) Input 2016 112 / 359
  • 126.
    Проблемы тестирования What’s up,Doc? (с) Проблема тестовых входных данных Проблема наблюдаемости Проблема «останова» Проблема тестового оракула Марат Ахин (СПбПУ) Input 2016 113 / 359
  • 127.
    Обеспечение порчи внутреннегосостояния Для того, чтобы обеспечить порчу внутреннего состояния (corruption), необходимо: обеспечить достижимость передать такие тестовые входные данные, которые вызывают нарушение целостности внутреннего состояния См. проблему тестовых входных данных Марат Ахин (СПбПУ) Input 2016 114 / 359
  • 128.
  • 129.
    Проблема наблюдаемости Software Testing101 Марат Ахин Санкт-Петербургский политехнический университет 2016 Марат Ахин (СПбПУ) PP 2016 116 / 359
  • 130.
  • 131.
  • 132.
    Проблемы тестирования What’s up,Doc? (с) Проблема тестовых входных данных Проблема наблюдаемости Проблема «останова» Проблема тестового оракула Марат Ахин (СПбПУ) PP 2016 119 / 359
  • 133.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных 6 Разработка через тестирование 7 Интеграционное тестирование 8 Проблема наблюдаемости Обеспечение распространения сбоя Марат Ахин (СПбПУ) PP 2016 120 / 359
  • 134.
    Обеспечение распространения сбоя Какимиспособами можно управлять выполнением кода? Изменением входных данных Изменением самого исходного кода Необходимо обнаружить сбой и распространить его, сделав наблюдаемым снаружи (Propagation) Марат Ахин (СПбПУ) PP 2016 121 / 359
  • 135.
  • 136.
    Assertions Основной способ обеспечениянаблюдаемости – assertions 1 private void checkInvariants () { 2 assert elements[tail] == null; 3 assert head == tail 4 ? elements[head] == null 5 : (elements[head] != null && 6 elements [( tail - 1) & (elements.length - 1)] != null ); 7 assert elements [( head - 1) & (elements.length - 1)] == null; 8 } Марат Ахин (СПбПУ) PP 2016 123 / 359
  • 137.
    Assertions Что такое assertion? Формулав логике первого порядка Проверяется на истинность во время выполнения программы Также может проверяться на истинность статически Допускает возможность отключения проверки истинности Марат Ахин (СПбПУ) PP 2016 124 / 359
  • 138.
    Что дает использованиеassertions? Проверка корректности внутреннего состояния Внутреннее состояние обычно недоступно снаружи (полностью или частично) При изменении состояния хочется проверить, что оно остается корректным Марат Ахин (СПбПУ) PP 2016 125 / 359
  • 139.
    Что дает использованиеassertions? Неудача происходит ближе к причине ее возникновения Чем больше задержка перед обнаружением неудачи, тем сложнее найти ее исходную причину Assertions позволяют найти неудачу практически в любой точке программы Марат Ахин (СПбПУ) PP 2016 126 / 359
  • 140.
    Что дает использованиеassertions? Явное документирование пред- и пост-условий В общем случае программист ничего не знает о контракте используемой функции Использование assertions позволяет в явном виде описать внешний контракт функции Марат Ахин (СПбПУ) PP 2016 127 / 359
  • 141.
  • 142.
    Какие проблемы связаныс assertions? Ошибки в assertions Побочные эффекты в assertions Неправильное логическое условие срабатывания Марат Ахин (СПбПУ) PP 2016 129 / 359
  • 143.
    Какие проблемы связаныс assertions? Влияние на производительность Проверка assertions занимает время Чем сложнее assertion, тем больше он замедляет работу программы Марат Ахин (СПбПУ) PP 2016 130 / 359
  • 144.
    Какие проблемы связаныс assertions? Эффект «вышибалы» Сработавший assertion превращает любую ошибку в неудачу Это полностью останавливает возможность дальнейшего тестирования Марат Ахин (СПбПУ) PP 2016 131 / 359
  • 145.
    Какие проблемы связаныс assertions? Сложность проверки определенных условий Некоторые просто формулируемые условия крайне сложно проверить на практике Их реализация в виде assertion является крайне затруднительной Марат Ахин (СПбПУ) PP 2016 132 / 359
  • 146.
    Работают ли assertions? МаратАхин (СПбПУ) PP 2016 133 / 359
  • 147.
    Работают ли assertions? 1int* ptr = malloc(sizeof(int) * 10); 2 assert(ptr); Адекватный assertion в правильном месте Марат Ахин (СПбПУ) PP 2016 134 / 359
  • 148.
    Работают ли assertions? 1int* ptr = malloc(sizeof(int) * 10); 2 assert(ptr); Замена обработки ошибок на assertion Марат Ахин (СПбПУ) PP 2016 135 / 359
  • 149.
    Работают ли assertions? МаратАхин (СПбПУ) PP 2016 136 / 359
  • 150.
    Работают ли assertions? MicrosoftOffice ≈ 1% Proprietary software ≈ 3% Open source software ≈ 5% Eiffel software ≈ 7% Сейчас assertions используются еще более широко Марат Ахин (СПбПУ) PP 2016 137 / 359
  • 151.
    Работают ли assertions?1 LLVM ≈500,000 SLOC ≈ 7000 assertions > 400 ошибок, относящихся к assertions 1 http://blog.regehr.org/ Марат Ахин (СПбПУ) PP 2016 138 / 359
  • 152.
    Работают ли assertions?1 GCC ≈1,000,000 SLOC ≈ 9500 assertions > 200 ошибок, относящихся к assertions 1 http://blog.regehr.org/ Марат Ахин (СПбПУ) PP 2016 138 / 359
  • 153.
    Работают ли assertions?2 1assert( BlockAddrFwdRefs .empty () && ...); 2 assert(Ty == V->getType () && ...); 3 assert ((Ty == 0 || Ty == V->getType ()) && ...); 4 assert(It != ResolveConstants .end() && ...); 5 assert(isa <ConstantExpr >( UserC) && ...); 6 assert(V->getType ()-> isMetadataTy () && ...); 7 assert ((! Alignment || isPowerOf2_32 (Alignment )) && ...); 8 assert (( Record[i] == 3 || Record[i] == 4) && ...); 9 assert(Record[i] == 0 && ...); 10 assert(Record[i] == 0 && ...); 11 assert(ResultTy && ...); 12 assert(TypeList[NumRecords] == 0 && ...); 13 assert(NextBitCode == bitc :: METADATA_NAMED_NODE ); 14 assert ((CT != LandingPadInst :: Catch 15 || !isa <ArrayType >(Val ->getType ())) && ...); 16 assert ((CT != LandingPadInst :: Filter 17 || isa <ArrayType >(Val ->getType ())) && ...); 18 assert(DFII != DeferredFunctionInfo .end () && ...); 19 assert( DeferredFunctionInfo .count(F) && ...); 20 assert(M == TheModule && ...); 2 http://blog.regehr.org/ Марат Ахин (СПбПУ) PP 2016 139 / 359
  • 154.
  • 155.
    Журналирование Журналирование (logging) Запись ходавыполнения программы в том или ином виде В зависимости от необходимости журнал может быть более или менее детализированным По журналу выполнения при необходимости возможно восстановить причину возникшей ошибки Марат Ахин (СПбПУ) PP 2016 141 / 359
  • 156.
    Журналирование Журналирование для пользователя Высокоуровневые сообщения Как можноменьше «мусора» Чем проще и понятнее формат сообщений, тем лучше Журналирование для программиста Низкоуровневые сообщения Допустим любой шум Никаких ограничений на формат сообщений Марат Ахин (СПбПУ) PP 2016 142 / 359
  • 157.
    Как вести журнал? 1Result :: Ptr processBatchJob (Job :: Ptr job) { 2 // do the heavy lifting ... 3 } Как записать ход выполнения программы? Марат Ахин (СПбПУ) PP 2016 143 / 359
  • 158.
    Как вести журнал? 1Result :: Ptr ThreadedProcessor :: processBatchJob (Job:: Ptr job) { 2 log () << "Start of: " << job << endl; 3 // do the heavy lifting ... 4 log () << "End of: " << job << endl; 5 } Ручная вставка журналирующих вызовов Марат Ахин (СПбПУ) PP 2016 144 / 359
  • 159.
    Как вести журнал? 1aspect ProcessTracer { 2 advice call("% %Processor :: process %(%)") : before () { 3 log () << "Start of: " << * JoinedPoint ::arg <0 >() << endl; 4 } 5 advice call("% %Processor :: process %(%)") : after () { 6 log () << "End of: " << *JoinedPoint ::arg <0 >() << endl; 7 } 8 }; Журналирующие аспекты / интерсепторы Марат Ахин (СПбПУ) PP 2016 145 / 359
  • 160.
    Как вести журнал? Loggingas a Service Марат Ахин (СПбПУ) PP 2016 146 / 359
  • 161.
    Основная проблема журналирования INFO[http -thread -pool -8080(5)] Received token: e6749451 TRACE [http -thread -pool -8080(5)] Calling: AuthStorageBean . getAuthData TRACE [http -thread -pool -8080(5)] Called: AuthStorageBean .getAuthData -> 2.0708E-5 INFO [http -thread -pool -8080(5)] Authentication data found: AuthData { authToken:e6749451 userId :1 firstName: lastName:Admin patrName: role:ru.korus.tmis.core.entity.model. Role[id=1] spec: } TRACE [http -thread -pool -8080(5)] Calling: AuthStorageBean . getAuthDateTime TRACE [http -thread -pool -8080(5)] Called: AuthStorageBean . getAuthDateTime -> 1.9825E-5 INFO [http -thread -pool -8080(5)] Token is valid TRACE [http -thread -pool -8080(5)] attempting to get session; create = false; session is null = true; session has id = false TRACE [http -thread -pool -8080(5)] Authentication attempt received for token [ru.korus.tmis .core.auth. TmisShiroToken@37bd2b6 ] DEBUG [http -thread -pool -8080(5)] Performing credentials equality check for tokenCredentials of type [java.lang.String and accountCredentials of type [java.lang .String] DEBUG [http -thread -pool -8080(5)] Both credentials arguments can be easily converted to byte arrays. Performing array equals comparison DEBUG [http -thread -pool -8080(5)] Authentication successful for token [ru.korus.tmis.core. auth. TmisShiroToken@37bd2b6 ]. Returned account [(admin ,ru.korus.tmis.core.entity. model.Role[id =1])] DEBUG [http -thread -pool -8080(5)] No SecurityManager available in subject context map. Falling back to SecurityUtils . getSecurityManager () lookup. Too much data! Марат Ахин (СПбПУ) PP 2016 147 / 359
  • 162.
    Основная проблема журналирования Чембольше мы хотим узнать о ходе выполнения программы, тем больше мы должны журналировать Чем больше мы журналируем, тем сложнее разобраться в журнале Чем сложнее разобраться в журнале, тем меньше мы знаем о ходе выполнения программы Марат Ахин (СПбПУ) PP 2016 148 / 359
  • 163.
    Ограничение размера журнала Необходимоограничивать размер записываемых данных Марат Ахин (СПбПУ) PP 2016 149 / 359
  • 164.
    Уровни журналирования Сообщения пишутсяв журнал с определенным уровнем В дальнейшем возможно фильтровать сообщения по уровням Error / Warning / Info / Debug / Trace Марат Ахин (СПбПУ) PP 2016 150 / 359
  • 165.
    Домены журналирования Домены ортогональныуровням журналирования В зависимости от типа сообщения пишутся в разные домены Database / Network / UI / Configuration / ... Марат Ахин (СПбПУ) PP 2016 151 / 359
  • 166.
    Стохастическое журналирование В случае,если какие-то события встречаются очень часто, достаточно записывать лишь их часть 1 if (_ok == true) { 2 _logger.log( Level.WARNING , "Server seen down: " + _addr , e ); 3 } else if (Math.random () < 0.1) { 4 _logger.log( Level.WARNING , "Server seen down: " + _addr ); 5 } Марат Ахин (СПбПУ) PP 2016 152 / 359
  • 167.
    Сессионное журналирование Часто работаПО разбита на набор слабо связанных сессий Каждая сессия может журналироваться независимо от других 1 try { 2 // logging ... 3 } catch (Exception ex) { 4 ctx.logging. dumpCurrentSession (); 5 throw; 6 } finally { 7 ctx.logging.reset (); 8 } Марат Ахин (СПбПУ) PP 2016 153 / 359
  • 168.
    Структурированное журналирование Вместо простоготекста журнал ведется в определенном формате Структурированный формат облегчает поиск и анализ по журналу 1 { 2 "session_id": "e6749451", 3 "event": " method_call", 4 "class_name": " AuthStorageBean ", 5 "method_name ": "getAuthData " 6 } Марат Ахин (СПбПУ) PP 2016 154 / 359
  • 169.
  • 170.
    Полнота тестирования ПО SoftwareTesting 101 Марат Ахин Санкт-Петербургский политехнический университет 2016 Марат Ахин (СПбПУ) TC 2016 156 / 359
  • 171.
  • 172.
  • 173.
    Проблемы тестирования What’s up,Doc? (с) Проблема тестовых входных данных Проблема наблюдаемости Проблема «останова» Проблема тестового оракула Марат Ахин (СПбПУ) TC 2016 159 / 359
  • 174.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных 6 Разработка через тестирование 7 Интеграционное тестирование 8 Проблема наблюдаемости Марат Ахин (СПбПУ) TC 2016 160 / 359
  • 175.
    Проблема «останова» втестировании Проблема останова По заданному алгоритму и входным данным определить, завершится ли за конечное время его выполнение При чем здесь тестирование?! Марат Ахин (СПбПУ) TC 2016 161 / 359
  • 176.
    Проблема «останова» втестировании Алгоритм ⇔ процесс тестирования Входные данные ⇔ тестируемая программа В подавляющем большинстве случаев процесс тестирования является бесконечным Марат Ахин (СПбПУ) TC 2016 162 / 359
  • 177.
    Проблема «останова» втестировании Мы не можем позволить себе тестировать бесконечное время Слишком долго Слишком дорого Слишком странно Что же делать? Марат Ахин (СПбПУ) TC 2016 163 / 359
  • 178.
    Проблема «останова» втестировании Останавливать процесс тестирования «вручную» Когда? У нас кончилось время и/или деньги на тестирование Мы протестировали ПО достаточно хорошо Марат Ахин (СПбПУ) TC 2016 164 / 359
  • 179.
    Проблема «останова» втестировании Проблема «останова» в тестировании По заданному набору тестов и программе определить, протестировали ли мы ее достаточно хорошо Что такое – достаточно хорошо? Марат Ахин (СПбПУ) TC 2016 165 / 359
  • 180.
    Тестовое покрытие Мы протестировалипрограмму достаточно хорошо, когда мы нашли большую часть ошибок в программе Чтобы найти ошибку, необходимо обеспечить выполнение трех основных свойств Обеспечение достижимости (reachability) и порчи (corruption) требует, чтобы мы выполнили определенный участок кода с определенными входными данными Качество тестирования можно оценить через тестовое покрытие Марат Ахин (СПбПУ) TC 2016 166 / 359
  • 181.
    Виды тестового покрытия Выделяютдва основных вида покрытия Покрытие потока управления Покрытие потока данных Они работают с такими понятиями, как граф потока управления (CFG) и граф потока данных (DFG) Надеюсь, что все знают, что такое CFG и DFG? Марат Ахин (СПбПУ) TC 2016 167 / 359
  • 182.
    Покрытие потока управления Какмы можем покрыть данный CFG? По узлам По дугам По условиям По путям ... Марат Ахин (СПбПУ) TC 2016 168 / 359
  • 183.
    Покрытие операторов программы Каждыйузел CFG был пройден в процессе тестирования хотя бы один раз Самый слабый способ оценки тестового покрытия Сколько тестов требуется для того, чтобы обеспечить полное покрытие операторов программы для следующего примера? Марат Ахин (СПбПУ) TC 2016 169 / 359
  • 184.
    Покрытие ветвлений программы Каждаяветка программы была пройдена хотя бы один раз Несколько более сильный способ оценки покрытия Сколько тестов требуется для того, чтобы обеспечить полное покрытие ветвлений программы для следующего примера? Марат Ахин (СПбПУ) TC 2016 170 / 359
  • 185.
    Покрытие ветвлений программы Каксоотносятся между собой покрытия операторов и ветвлений? 1 Никак 2 Покрытие операторов включает покрытие ветвлений 3 Покрытие ветвлений включает покрытие операторов Марат Ахин (СПбПУ) TC 2016 171 / 359
  • 186.
    Покрытие ветвлений программы Никак Почемупокрытие ветвлений не включает в себя покрытие операторов? Потому что в программе может присутствовать «мертвый код» Потому что в программе могут вообще отсутствовать ветвления Марат Ахин (СПбПУ) TC 2016 172 / 359
  • 187.
    Покрытие условий программы Каждоеветвление может выполняться по различным причинам При покрытии условий программы мы требуем, чтобы все условия ветвлений хотя бы один раз приняли значение true и false 1 if (req.isSsl () && (cfg.SslEnabled () || cfg.isDebug ())) { 2 ... 3 } Как соотносятся между собой покрытия ветвлений и условий? Марат Ахин (СПбПУ) TC 2016 173 / 359
  • 188.
    Покрытие условий программы Никак Разныекомбинации условий могут приводить к выбору одного и того же ветвления 1 if (req. isLocalhost () || cfg.isDebug () || cfg.isDevMode ()) { 2 ... 3 } Марат Ахин (СПбПУ) TC 2016 174 / 359
  • 189.
    Покрытие ветвлений иусловий программы Комбинация соответствующих покрытий Полностью их покрывает Можно ли предложить что-то более сильное? 1 if (req.isSsl () && (cfg.SslEnabled () || cfg.isDebug ())) { 2 ... 3 } Марат Ахин (СПбПУ) TC 2016 175 / 359
  • 190.
    Модифицированное покрытие ветвленийи условий Также известное как MC/DC Является одним из обязательных условий при тестировании ПО на уровень A в рамках DO-178B Чем оно отличается от обычного покрытия ветвлений и условий программы? 1 if (req.isSsl () && (cfg.SslEnabled () || cfg.isDebug ())) { 2 ... 3 } Марат Ахин (СПбПУ) TC 2016 176 / 359
  • 191.
    Модифицированное покрытие ветвленийи условий Каждое условие независимо повлияло на выполнение программы Как это проверить? Изменить одно условие и проверить, изменилось ли ветвление 1 if (req.isSsl () && (cfg.SslEnabled () || cfg.isDebug ())) { 2 ... 3 } Марат Ахин (СПбПУ) TC 2016 177 / 359
  • 192.
    Полное покрытие условийпрограммы Полный перебор всех возможных комбинаций условий всех возможных ветвлений Сколько вариантов необходимо перебрать, чтобы получить полное комбинационное покрытие для следующего примера? 1 if (req.isSsl () && (cfg.SslEnabled () || cfg.isDebug ())) { 2 ... 3 } Марат Ахин (СПбПУ) TC 2016 178 / 359
  • 193.
    Покрытие путей программы Мытребуем, чтобы все возможные пути программы были выполнены хотя бы один раз Как данное покрытие соотносится с полным покрытием условий? Обычно считается самым сильным типом покрытия потока управления Его можно было бы использовать, если бы не... Циклы и рекурсия Марат Ахин (СПбПУ) TC 2016 179 / 359
  • 194.
    Покрытие путей программы Мытребуем, чтобы все возможные пути программы были выполнены хотя бы один раз Как данное покрытие соотносится с полным покрытием условий? Обычно считается самым сильным типом покрытия потока управления Его можно было бы использовать, если бы не... Циклы и рекурсия Марат Ахин (СПбПУ) TC 2016 179 / 359
  • 195.
    Покрытие путей программы Мытребуем, чтобы все возможные пути программы были выполнены хотя бы один раз Как данное покрытие соотносится с полным покрытием условий? Обычно считается самым сильным типом покрытия потока управления Его можно было бы использовать, если бы не... Циклы и рекурсия Марат Ахин (СПбПУ) TC 2016 179 / 359
  • 196.
    Покрытие путей программы 450возможных путей Марат Ахин (СПбПУ) TC 2016 180 / 359
  • 197.
    Покрытие путей программы 450возможных путей Марат Ахин (СПбПУ) TC 2016 180 / 359
  • 198.
    Покрытие путей программы Дляборьбы с этим используют несколько подходов Один из вариантов Требуем, чтобы тело цикла было выполнено 0 1 k max Объясните, почему выбраны именно эти варианты Марат Ахин (СПбПУ) TC 2016 181 / 359
  • 199.
    Покрытие потока данных Чтоеще можно сделать? Можно вспомнить о том, что программы работают не просто так Основная цель работы любой программы – работа с данными С этой точки зрения для тестирования представляет интерес анализ таких путей выполнения программы, на которых активно работают с данными Сперва вспомним несколько определений Марат Ахин (СПбПУ) TC 2016 182 / 359
  • 200.
    Определения и использованияпеременных Определение переменной (Def) Оператор программы, в котором значение переменной v может быть изменено v = 42 f(&v, ...) scanf(fmt, &v) Использование переменной (Use) Оператор программы, в котором значение переменной v влияет на выполнение программы тем или иным способом q = v + 2 g(v, ...) if (v != NULL) ... Марат Ахин (СПбПУ) TC 2016 183 / 359
  • 201.
    Определения и использованияпеременных Def-Use Chain Пара (d, u) операторов программы, для которой выполняются следующие условия d – определение переменной v u – использование переменной v между d и u существует хотя бы один путь, на котором переменная v не переопределяется Рассмотрим данные определения на примере Марат Ахин (СПбПУ) TC 2016 184 / 359
  • 202.
  • 203.
    Покрытие потока данных Какиеварианты покрытий можно предложить с использованием этих понятий? Покрытие всех определений Для каждой интересующей нас переменной v должна быть протестирована хотя бы одна Def-Use Chain от каждого определения v до хотя бы одного использования v Марат Ахин (СПбПУ) TC 2016 186 / 359
  • 204.
    All-Def Coverage Рассмотрим следующиетесты 1 → 2 → 3 → 4 → 5 → 6 Марат Ахин (СПбПУ) TC 2016 187 / 359
  • 205.
    Покрытие потока данных Покрытиевсех использований Для каждой интересующей нас переменной v должна быть протестирована хотя бы одна Def-Use Chain от каждого определения v до каждого использования v Является ли All-Use более сильным критерием по сравнению с All-Def? Марат Ахин (СПбПУ) TC 2016 188 / 359
  • 206.
    All-Use Coverage Рассмотрим следующиетесты 1 → 2 → 3 → 4 → 5 → 6 1 → 2 → 3 → 4 → 6 1 → 3 → 4 → 5 → 6 Марат Ахин (СПбПУ) TC 2016 189 / 359
  • 207.
    Покрытие потока данных Покрытиевсех Def-Use Chain Для каждой интересующей нас переменной v должны быть протестированы все возможные Def-Use Chain от каждого определения v до каждого использования v Как соотносится All-Def-Use-Chain с покрытием всех путей программы? Марат Ахин (СПбПУ) TC 2016 190 / 359
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
    Другой способ оценкиполноты Какими способами можно управлять выполнением кода? Изменением входных данных Изменением самого исходного кода Как можно оценить полноту тестирования, изменяя исходный код? Марат Ахин (СПбПУ) TC 2016 195 / 359
  • 213.
    Идеальный тест Идеальный тестработает только на тестируемой программе При любом изменений он перестает проходить В этом заключается основная идея мутационного тестирования Марат Ахин (СПбПУ) TC 2016 196 / 359
  • 214.
    Мутационное тестирование Исходная программаподвергается мутации, в результате получается набор из N мутантов После этого имеющиеся тесты запускаются на этих мутантах Если тест не проходит на мутанте, то говорят, что тест «убивает» этого мутанта Доля «убитых» мутантов показывает, насколько полно данный набор тестов покрывает нашу программу Марат Ахин (СПбПУ) TC 2016 197 / 359
  • 215.
    Как сделать мутанта? Чтоможно сделать с исходным кодом? Добавить новый код Удалить старый код Изменить существующий код Набор синтаксических трансформаций, изменяющих исходный код Марат Ахин (СПбПУ) TC 2016 198 / 359
  • 216.
    Как сделать мутанта? 1int sumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Как можно мутировать данный фрагмент кода? Марат Ахин (СПбПУ) TC 2016 199 / 359
  • 217.
    Как сделать мутанта? Некоторыемутанты будут синтаксически некорректны Другие мутанты будут семантически некорректны Оставшиеся мутанты подходят для использования в мутационном тестировании Какие проблемы есть у мутационного тестирования? Марат Ахин (СПбПУ) TC 2016 200 / 359
  • 218.
    Недостатки мутационного тестирования Данныйвид тестирования практически невозможно выполнять вручную Количество необходимых для оценки покрытия мутантов пропорционально объему анализируемого ПО Даже для небольшой программы получение достаточного числа мутантов вручную является практически невозможным Сильно возрастают затраты на проведение тестирования Вместо одного запуска каждого теста требуется выполнить N запусков Кроме того, дополнительное время тратится на генерацию мутантов Марат Ахин (СПбПУ) TC 2016 201 / 359
  • 219.
  • 220.
  • 221.
  • 222.
    Оценка тестового покрытия Мыже уже поговорили об оценке тестового покрытия? Оценка тестового покрытия программы Оценка самого тестового покрытия Who observes the observer? c Марат Ахин (СПбПУ) TC 2016 205 / 359
  • 223.
    Оценка тестового покрытия Какаяпроблема есть у покрытия потока управления? Чувствительность к изменениям в исходном коде Марат Ахин (СПбПУ) TC 2016 206 / 359
  • 224.
    Оценка тестового покрытия Какаяпроблема есть у покрытия потока управления? Чувствительность к изменениям в исходном коде Марат Ахин (СПбПУ) TC 2016 206 / 359
  • 225.
    Нестабильность тестового покрытия 1... 2 if (a && b && c) { 3 ... 4 } 1 bool cond = a && b && c; 2 if (cond) { 3 ... 4 } Что будет с покрытием MC/DC? Марат Ахин (СПбПУ) TC 2016 207 / 359
  • 226.
    Нестабильность тестового покрытия Чемсильнее влияют изменения в программе на тестовое покрытие, тем более нестабильным (fragile) является тестовое покрытие Чем более нестабильным является тестовое покрытие, тем менее адекватно оно оценивает качество тестирования Что же делать? Марат Ахин (СПбПУ) TC 2016 208 / 359
  • 227.
    Оценка тестового покрытия Thewhole is more than the sum of its parts c Можно применить мутационное тестирование для оценки тестового покрытия Ограничить набор трансформаций Посмотреть на изменение тестового покрытия для мутантов ... PROFIT! Марат Ахин (СПбПУ) TC 2016 209 / 359
  • 228.
    Оценка тестового покрытия Какаяпроблема есть у мутационного тестирования? Эквивалентные мутанты Марат Ахин (СПбПУ) TC 2016 210 / 359
  • 229.
    Оценка тестового покрытия Какаяпроблема есть у мутационного тестирования? Эквивалентные мутанты Марат Ахин (СПбПУ) TC 2016 210 / 359
  • 230.
    Эквивалентные мутанты 1 intsumCollection (final @NotNull Collection <Integer > c) { 2 int sum = 0; 3 for (int i : c) { 4 sum += i; 5 } 6 return sum; 7 } Почему эквивалентные мутанты – это плохо? Марат Ахин (СПбПУ) TC 2016 211 / 359
  • 231.
    Эквивалентные мутанты Эквивалентные мутанты«зашумляют» итоговую оценку качества тестирования Из-за шума снижается адекватность оценки Что же делать? Марат Ахин (СПбПУ) TC 2016 212 / 359
  • 232.
    Оценка тестового покрытия Thewhole is more than the sum of its parts c Можно применить тестовое покрытие для оценки мутационного тестирования Для каждого мутанта записывается трасса его выполнения У эквивалентных мутантов будут похожие трассы выполнения ... PROFIT! Марат Ахин (СПбПУ) TC 2016 213 / 359
  • 233.
  • 234.
    Тестовый оракул: что,где, когда Software Testing 101 Марат Ахин Санкт-Петербургский политехнический университет 2016 Марат Ахин (СПбПУ) TO 2016 215 / 359
  • 235.
  • 236.
  • 237.
    Проблемы тестирования What’s up,Doc? (с) Проблема тестовых входных данных Проблема наблюдаемости Проблема «останова» Проблема тестового оракула Марат Ахин (СПбПУ) TO 2016 218 / 359
  • 238.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных 6 Разработка через тестирование 7 Интеграционное тестирование 8 Проблема наблюдаемости Марат Ахин (СПбПУ) TO 2016 219 / 359
  • 239.
    Тестовый оракул Magic 8-ballтестирования Марат Ахин (СПбПУ) TO 2016 220 / 359
  • 240.
  • 241.
    Тестовый оракул В чемзаключается проблема тестового оракула? Его нет! Марат Ахин (СПбПУ) TO 2016 222 / 359
  • 242.
    Тестовый оракул Вид тестовогооракула очень сильно зависит от того, какую эталонную модель мы используем kd-tree stoi md5sum PDF reader Марат Ахин (СПбПУ) TO 2016 223 / 359
  • 243.
  • 244.
    Точность Способность оракула избегатьложных обнаружений Ложные обнаружения при тестировании – лишние затраты на их обнаружение и игнорирование Если их будет слишком много, оракул никто не будет использовать из-за зашумления результатов Марат Ахин (СПбПУ) TO 2016 225 / 359
  • 245.
    Полнота Способность оракула находитьвсе ошибки Пропущенные ошибки при тестировании – дополнительные затраты на их исправление позднее Если оракул пропускает много ошибок, его необходимо усиливать другими способами Марат Ахин (СПбПУ) TO 2016 226 / 359
  • 246.
    Виды тестовых оракулов Варьируяиспользуемые подходы, можно получить те или иные виды тестовых оракулов Слабые Средние Сильные Марат Ахин (СПбПУ) TO 2016 227 / 359
  • 247.
    Слабые оракулы Падение Segmentation fault Coredump Работают всегда Практически ничего не говорят о причине ошибки Марат Ахин (СПбПУ) TO 2016 228 / 359
  • 248.
    Слабые оракулы Сбой приработе в обычном окружении NullPointerException OutOfMemoryException ClassNotFoundException Работают при поддержке стандартной среды выполнения Содержат определенную информацию о месте ошибки Марат Ахин (СПбПУ) TO 2016 229 / 359
  • 249.
    Слабые оракулы Сбой приработе в специальном тестовом окружении Valgrind Предоставляют специальную среду выполнения Позволяют весьма точно определить причину ошибок Марат Ахин (СПбПУ) TO 2016 230 / 359
  • 250.
    Valgrind Фреймворк для построениясредств динамического анализа программ Включает встроенные реализации для Memcheck Cachegrind Callgrind Helgrind DRD Massif DHAT ... Марат Ахин (СПбПУ) TO 2016 231 / 359
  • 251.
    Слабые оракулы Хорошая точность Плохаяполнота Марат Ахин (СПбПУ) TO 2016 232 / 359
  • 252.
    Средние оракулы Assertions Тесты Требуют определенныхусилий со стороны разработчиков В зависимости от степени усилий, будут более или менее точно указывать на место возникновения ошибки Марат Ахин (СПбПУ) TO 2016 233 / 359
  • 253.
    Средние оракулы Хорошая точность Средняяполнота Марат Ахин (СПбПУ) TO 2016 234 / 359
  • 254.
    Сильные оракулы Эталонная реализация Предыдущаяверсия программы Формально верифицированная реализация Автоматически сгенерированная версия Марат Ахин (СПбПУ) TO 2016 235 / 359
  • 255.
    Сильные оракулы «Обратная функция» Прямое/обратноепреобразование Фурье Архиватор/деархиватор Кодер/декодер видео Марат Ахин (СПбПУ) TO 2016 236 / 359
  • 256.
    Сильные оракулы Средняя точность Хорошаяполнота Марат Ахин (СПбПУ) TO 2016 237 / 359
  • 257.
    Генерация оракулов Можно лигенерировать оракула автоматически? Да! Слабые оракулы Средние оракулы Марат Ахин (СПбПУ) TO 2016 238 / 359
  • 258.
    Генерация оракулов Можно лигенерировать оракула автоматически? Да! Слабые оракулы Средние оракулы Марат Ахин (СПбПУ) TO 2016 238 / 359
  • 259.
    Генерация слабых оракулов Всеуже есть Слабый оракул предоставляется средой выполнения Если что-то упало, мы всегда об этом узнаем Марат Ахин (СПбПУ) TO 2016 239 / 359
  • 260.
    Генерация слабых оракулов Вявном виде используются весьма редко Случайное тестирование ... Сложно понять, где произошла ошибка Не всегда очевидно, в чем именно заключается ошибка Марат Ахин (СПбПУ) TO 2016 240 / 359
  • 261.
  • 262.
    Генерация средних оракулов Всеуже есть Средние оракулы разрабатываются параллельно с разработкой ПО При возникновении проблемы мы сразу узнаем о ней Зачем их генерировать автоматически? Марат Ахин (СПбПУ) TO 2016 242 / 359
  • 263.
  • 264.
    Генерация assertions Assertions проверяюткорректность внутреннего состояния Как автоматически сгенерировать assertions? Machine learning Марат Ахин (СПбПУ) TO 2016 244 / 359
  • 265.
    Генерация assertions Собираем информациюо выполнении программы Выводим определенные закономерности в работе программы Генерируем assertion, проверяющий ненарушение закономерностей ... PROFIT! Хорошо работает для FSM-подобных программ Плохо работает для всех остальных Марат Ахин (СПбПУ) TO 2016 245 / 359
  • 266.
    Генерация assertions Собираем информациюо выполнении программы В случае падения определяем его причину Генерируем защитный assertion ... PROFIT! Способ усиления слабых оракулов до средних Не работает, если ничего не падает Марат Ахин (СПбПУ) TO 2016 246 / 359
  • 267.
    Генерация тестов Тесты –один из видов эталонной модели поведения Как автоматически сгенерировать эталонную модель? Мутационное тестирование Марат Ахин (СПбПУ) TO 2016 247 / 359
  • 268.
    Генерация тестов Вспомним, что: Идеальныйтест работает только на тестируемой программе Если тест проходит на мутанте, это плохо Собираем информацию о выполнении оригинальной программы и мутанта Анализируем разницу ... PROFIT! Марат Ахин (СПбПУ) TO 2016 248 / 359
  • 269.
    Генерация тестов дляGUI А если у нас есть GUI??? Что такое разница в работе GUI? Как можно автоматически ее обнаружить? Марат Ахин (СПбПУ) TO 2016 249 / 359
  • 270.
    Генерация тестов дляGUI Нужна модель самого GUI Нужна модель изменений GUI Извлечение моделей должно выполняться автоматически Марат Ахин (СПбПУ) TO 2016 250 / 359
  • 271.
    Генерация тестов Можно липридумать что-то еще? Случайное тестирование Марат Ахин (СПбПУ) TO 2016 251 / 359
  • 272.
  • 273.
    Случайное тестирование Software Testing101 Марат Ахин Санкт-Петербургский политехнический университет 2016 Марат Ахин (СПбПУ) RT 2016 253 / 359
  • 274.
  • 275.
  • 276.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных 6 Разработка через тестирование 7 Интеграционное тестирование 8 Проблема наблюдаемости Марат Ахин (СПбПУ) RT 2016 256 / 359
  • 277.
    Генерация тестов Развитие идеигенерации тестовых оракулов Полная автоматизация процесса тестирования Марат Ахин (СПбПУ) RT 2016 257 / 359
  • 278.
    Генерация тестов Основная идея Заставитькомпьютер работать вместо нас Дешевле Быстрее Нет человеческого фактора Марат Ахин (СПбПУ) RT 2016 258 / 359
  • 279.
    Генерация тестов Автоматическая генерациякомпонентов тестов Входные данные Последовательности вызовов API Тестовые оракулы Марат Ахин (СПбПУ) RT 2016 259 / 359
  • 280.
    Генерация тестов Результаты оченьсильно зависят от того, что именно мы тестируем... kd-tree stoi md5sum PDF reader Марат Ахин (СПбПУ) RT 2016 260 / 359
  • 281.
    Fuzzing Прародитель случайного тестирования Полностьюслучайные данные Вариант smoke testing P8FT8PjBG7s71Bw1a8EP4svDPL5g4E791 TJcs5t9ZbxQAsLZx436PdJcxk3vq61192 Марат Ахин (СПбПУ) RT 2016 261 / 359
  • 282.
    Fuzzing Используем слабые оракулы Принеобходимости вставляем заглушки Что такое случайные данные? Набор байт Вызовы функций API Пользовательский ввод Марат Ахин (СПбПУ) RT 2016 262 / 359
  • 283.
    Fuzzing 1989 – первоеприменение фаззинга на утилитах *NIX 1995 – повторная проверка утилит *NIX 2000 – проверка Windows NT/Windows 2000 2006 – проверка утилит Mac OS X Стали ли результаты лучше? Марат Ахин (СПбПУ) RT 2016 263 / 359
  • 284.
    Fuzzing Нет! Все стало ещехуже! GUI: 26% -> 45% -> 64% -> 73% Многие баги, обнаруженные фаззингом, были исправлены... ...но появилось еще больше новых! Марат Ахин (СПбПУ) RT 2016 264 / 359
  • 285.
  • 286.
    Fuzzing md5sum kd-tree stoi PDF reader Работает длявсех программ Но есть одно «но»... c Марат Ахин (СПбПУ) RT 2016 266 / 359
  • 287.
    Проблема валидности данных Полностьюслучайные данные являются невалидными входными данными для большинства программ Марат Ахин (СПбПУ) RT 2016 267 / 359
  • 288.
    Проблема валидности данных Большинствопрограмм ожидают структурированные входные данные P8FT8PjBG7s71Bw1a8EP4svDPL5g4E791 TJcs5t9ZbxQAsLZx436PdJcxk3vq61192 vs 3.1415926535897932384626433832797 [(1,0,0),(0,1,0),(0,0,1),(1,1,1)] Марат Ахин (СПбПУ) RT 2016 268 / 359
  • 289.
    Generative random testing Еслимы знаем структуру, то мы можем ей воспользоваться Генерируем отдельные элементы Комбинируем их в соответствии с заданной структурой Вносим случайные нарушения структуры Марат Ахин (СПбПУ) RT 2016 269 / 359
  • 290.
    Generative random testing Чтотакое структура? Набор правил генерации Грамматика Формальная спецификация Стандарт на формат входных файлов Марат Ахин (СПбПУ) RT 2016 270 / 359
  • 291.
    Generative random testing kd-tree stoi PDFreader Работает для структурированных входных данных Но есть одно «но»... c Марат Ахин (СПбПУ) RT 2016 271 / 359
  • 292.
    Проблема сложной структуры Иногдаструктура входных данных является слишком сложной Марат Ахин (СПбПУ) RT 2016 272 / 359
  • 293.
    Mutation random testing Обычноу нас есть какой-то набор тестовых входных данных Подвергаем тестовые данные мутации При этом возможно использование знания структуры данных Часть данных может генерироваться случайно Марат Ахин (СПбПУ) RT 2016 273 / 359
  • 294.
    Mutation random testing Какиемогут быть мутационные трансформации? Добавление нового фрагмента Удаление старого фрагмента Изменение фрагмента Обмен двух фрагментов местами Замена значений на граничные Марат Ахин (СПбПУ) RT 2016 274 / 359
  • 295.
    Mutation random testing PDFreader Web browser Работает практически для всего Но есть одно «но»... c Марат Ахин (СПбПУ) RT 2016 275 / 359
  • 296.
    Проблема скелета вшкафу Добраться до самых дальних закоулков нельзя Марат Ахин (СПбПУ) RT 2016 276 / 359
  • 297.
    Directed random testing Вчем заключаются основные проблемы случайного тестирования? Некорректные тесты Эквивалентные тесты Длинные тесты Марат Ахин (СПбПУ) RT 2016 277 / 359
  • 298.
    Directed random testing МаратАхин (СПбПУ) RT 2016 278 / 359
  • 299.
    Directed random testing Некорректныетесты Более строгие правила генерации/мутации Явный учет некорректных тестов Марат Ахин (СПбПУ) RT 2016 279 / 359
  • 300.
    Directed random testing Эквивалентныетесты Обнаружение тестов, на которых программа ведет себя одинаковым образом Статически Динамически Вспомним про тестовое покрытие... Марат Ахин (СПбПУ) RT 2016 280 / 359
  • 301.
    Directed random testing Длинныетесты Минимизация тестов Дихотомия Стохастический поиск Эволюционные алгоритмы Delta debugging Марат Ахин (СПбПУ) RT 2016 281 / 359
  • 302.
    Directed random testing Аможно ли еще лучше? Каждый новый тест минимально отличается от имеющихся Каждый новый тест улучшает тестовое покрытие Каждый новый тест должен генерироваться достаточно быстро Марат Ахин (СПбПУ) RT 2016 282 / 359
  • 303.
    Concolic testing Concolic testing Комбинируеминформацию о конкретных выполнениях программы... ...и информацию о символическом поведении программы Комбинация статического и динамического анализов Марат Ахин (СПбПУ) RT 2016 283 / 359
  • 304.
    Satisfiability modulo theories 1void f(int x) { 2 int y = x^2; 3 4 bool A = x > 0; 5 bool B = x < 10; 6 bool C = y > 20; 7 8 if (B && C) { 9 if (A) { 10 ... 11 } 12 } 13 } SMT to the rescue 1 x, y = Ints(’x y’) 2 A, B, C = Bools(’A B C’) 3 4 s = Solver () 5 6 s.add(y == x * x) 7 s.add(A == (x > 0)) 8 s.add(B == (x < 10)) 9 s.add(C == (y > 20)) Марат Ахин (СПбПУ) RT 2016 284 / 359
  • 305.
    Satisfiability modulo theories 1print s.check(B and C, A) 2 print s.model () 3 # sat 4 # [A = True , B = True , y = 25, x = 5, C = True] 5 6 print s.check(B and C, Not(A)) 7 print s.model () 8 # sat 9 # [A = False , B = True , y = 25, x = -5, C = True] 10 11 print s.check(Not(B and C)) 12 print s.model () 13 # sat 14 # [A = False , B = True , y = 0, x = 0, C = False] Марат Ахин (СПбПУ) RT 2016 285 / 359
  • 306.
    Проблемы concolic testing Почемуя слышу об этом впервые в жизни? Это сложно Это очень сложно Это очень-очень сложно Марат Ахин (СПбПУ) RT 2016 286 / 359
  • 307.
    Проблемы concolic testing Инструментированиепрограммы Моделирование памяти Взрыв пространства состояний Оптимизации! Марат Ахин (СПбПУ) RT 2016 287 / 359
  • 308.
    Concolic testing SAGE Microsoft Research 500+машино-лет Более трети всех багов в различных проектах Microsoft Развивается вместе с тестируемым им ПО Марат Ахин (СПбПУ) RT 2016 288 / 359
  • 309.
    Directed random testing VisualStudio Microsoft Office Работает для всего Но есть одно «но»... c Марат Ахин (СПбПУ) RT 2016 289 / 359
  • 310.
    Проблема мистера Икс Некоторыечасти системы могут быть «черным ящиком» Марат Ахин (СПбПУ) RT 2016 290 / 359
  • 311.
  • 312.
    Регрессионное тестирование Software Testing101 Марат Ахин Санкт-Петербургский политехнический университет 2016 Марат Ахин (СПбПУ) RT 2016 292 / 359
  • 313.
  • 314.
  • 315.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных 6 Разработка через тестирование 7 Интеграционное тестирование 8 Проблема наблюдаемости Марат Ахин (СПбПУ) RT 2016 295 / 359
  • 316.
    Тестирование ПО впроцессе разработки Как ПО изменяется в процессе разработки? Инкрементально, небольшими независимыми шагами Изменение уже существующего кода Исправление ошибок Добавление новой функциональности Адаптация имеющихся компонентов к новым задачам Любые (даже самые незначительные) изменения могут серьезно повлиять на качество ПО Марат Ахин (СПбПУ) RT 2016 296 / 359
  • 317.
    Тестирование ПО впроцессе разработки Как ПО изменяется в процессе разработки? Инкрементально, небольшими независимыми шагами Изменение уже существующего кода Исправление ошибок Добавление новой функциональности Адаптация имеющихся компонентов к новым задачам Любые (даже самые незначительные) изменения могут серьезно повлиять на качество ПО Марат Ахин (СПбПУ) RT 2016 296 / 359
  • 318.
    Тестирование ПО впроцессе разработки Как ПО изменяется в процессе разработки? Инкрементально, небольшими независимыми шагами Изменение уже существующего кода Исправление ошибок Добавление новой функциональности Адаптация имеющихся компонентов к новым задачам Любые (даже самые незначительные) изменения могут серьезно повлиять на качество ПО Марат Ахин (СПбПУ) RT 2016 296 / 359
  • 319.
    Тестирование ПО впроцессе разработки После любого изменения требуется проверить, что в программе не появилось новых ошибок Для этого мы выполняем все имеющиеся тесты и проверяем, что все они успешно завершаются Основной вид тестирования в процессе разработки ПО – это регрессионное тестирование Марат Ахин (СПбПУ) RT 2016 297 / 359
  • 320.
    Регрессионное тестирование Как выглядитодна итерация регрессионного тестирования? 1 Мы модифицируем программу P и получаем программу P 2 Из всего множества тестов T мы выбираем набор тестов T , который необходимо выполнить на P 3 Для новой функциональности мы разрабатываем новые тесты T 4 Полученный набор тестов T + T запускается на P 5 Результаты выполнения анализируются с последующей возможной модификацией как программы, так и набора тестов Какие проблемы связаны с РТ? Марат Ахин (СПбПУ) RT 2016 298 / 359
  • 321.
    Регрессионное тестирование Проблема №1 Каквыбрать набор тестов T после изменения в программе? Консервативный подход Выбираем все имеющиеся тесты Полное регрессионное тестирование Случайный подход Выбираем случайное подмножество всех тестов Случайное выборочное регрессионное тестирование Марат Ахин (СПбПУ) RT 2016 299 / 359
  • 322.
    Регрессионное тестирование Каким свойствамдолжно удовлетворять выборочное регрессионное тестирование? Полнота – способность выбирать те тесты, которые могут обнаружить ошибки, связанные с изменениями в коде Точность – способность пропускать такие тесты, которые не изменяют своего поведения на модифицированной программе Эффективность – способность выполняться быстрее, чем полное регрессионное тестирование Универсальность – применимость в большинстве практических ситуаций «Качественно. Быстро. Дешево. Выберите любые два.» Марат Ахин (СПбПУ) RT 2016 300 / 359
  • 323.
    Регрессионное тестирование Умный подход Выбиратьтесты, которые «затрагивают» при выполнении измененные части программы Выборочное регрессионное тестирование Все подходы к ВРТ различаются по двум основным критериям Способ идентификации измененных программных компонентов Метод получения информации о покрытии элементов программы тестами Марат Ахин (СПбПУ) RT 2016 301 / 359
  • 324.
    Подход МакКарти Анализ измененийна уровне целого модуля Связь элементов программы с тестами задается вручную разработчиком Преимущества и недостатки? Марат Ахин (СПбПУ) RT 2016 302 / 359
  • 325.
    Подход на основеконцепции файервола Анализ изменений на уровне целых модулей Связь элементов программы с тестами задается вручную разработчиком Преимущества и недостатки? Марат Ахин (СПбПУ) RT 2016 303 / 359
  • 326.
    Подход Ротермела иХарролд Анализ изменений на уровне узлов CFG программы Связь элементов программы с тестами задается на уровне CFG на основе динамической информации о выполнении каждого теста Преимущества и недостатки? Марат Ахин (СПбПУ) RT 2016 304 / 359
  • 327.
    Подход Балла Анализ измененийна уровне узлов CFG программы Связь элементов программы с тестами задается на уровне CFG на основе динамической информации о выполнении каждого теста Преимущества и недостатки? Марат Ахин (СПбПУ) RT 2016 305 / 359
  • 328.
    Подход на основеAST Анализ изменений на уровне вершин AST программы Связь элементов программы с тестами задается на уровне AST на основе динамической информации о выполнении каждого теста Преимущества и недостатки? Марат Ахин (СПбПУ) RT 2016 306 / 359
  • 329.
    Управление регрессионными тестами Проблема№2 Как управлять набором регрессионных тестов? Когда и как добавлять в набор новые тесты? Когда можно удалять старые тесты? Марат Ахин (СПбПУ) RT 2016 307 / 359
  • 330.
    Добавление новых тестов Когданадо добавлять новый регрессионный тест? Когда в ПО появилась новая функциональность Когда в ПО была исправлена ошибка Когда мы хотим улучшить тестовое покрытие ПО Когда мы можем себе позволить добавить новый неповторяющийся тест Марат Ахин (СПбПУ) RT 2016 308 / 359
  • 331.
    Добавление новых тестов Когданадо добавлять новый регрессионный тест? Когда в ПО появилась новая функциональность Когда в ПО была исправлена ошибка Когда мы хотим улучшить тестовое покрытие ПО Когда мы можем себе позволить добавить новый неповторяющийся тест Марат Ахин (СПбПУ) RT 2016 308 / 359
  • 332.
    Добавление новых тестов Когданадо добавлять новый регрессионный тест? Когда в ПО появилась новая функциональность Когда в ПО была исправлена ошибка Когда мы хотим улучшить тестовое покрытие ПО Когда мы можем себе позволить добавить новый неповторяющийся тест Марат Ахин (СПбПУ) RT 2016 308 / 359
  • 333.
    Добавление новых тестов Когданадо добавлять новый регрессионный тест? Когда в ПО появилась новая функциональность Когда в ПО была исправлена ошибка Когда мы хотим улучшить тестовое покрытие ПО Когда мы можем себе позволить добавить новый неповторяющийся тест Марат Ахин (СПбПУ) RT 2016 308 / 359
  • 334.
    Добавление новых тестов Стечением времени число тестов увеличивается Чем больше тестов, тем лучше тестовое покрытие Проблемы начинаются, когда тестов становится слишком много Что такое «слишком много»? Марат Ахин (СПбПУ) RT 2016 309 / 359
  • 335.
    Удаление старых тестов Когдаможно удалять старый тест? Никогда Когда тест дублирует другие тесты Когда тест не улучшает тестовое покрытие Когда тест ни разу не обнаружил ошибки за все время тестирования Когда тест обнаруживает такие же ошибки, как и другие тесты Марат Ахин (СПбПУ) RT 2016 310 / 359
  • 336.
    Удаление старых тестов Когдаможно удалять старый тест? Никогда Когда тест дублирует другие тесты Когда тест не улучшает тестовое покрытие Когда тест ни разу не обнаружил ошибки за все время тестирования Когда тест обнаруживает такие же ошибки, как и другие тесты Марат Ахин (СПбПУ) RT 2016 310 / 359
  • 337.
    Удаление старых тестов Когдаможно удалять старый тест? Никогда Когда тест дублирует другие тесты Когда тест не улучшает тестовое покрытие Когда тест ни разу не обнаружил ошибки за все время тестирования Когда тест обнаруживает такие же ошибки, как и другие тесты Марат Ахин (СПбПУ) RT 2016 310 / 359
  • 338.
    Удаление старых тестов Когдаможно удалять старый тест? Никогда Когда тест дублирует другие тесты Когда тест не улучшает тестовое покрытие Когда тест ни разу не обнаружил ошибки за все время тестирования Когда тест обнаруживает такие же ошибки, как и другие тесты Марат Ахин (СПбПУ) RT 2016 310 / 359
  • 339.
    Удаление старых тестов Когдаможно удалять старый тест? Никогда Когда тест дублирует другие тесты Когда тест не улучшает тестовое покрытие Когда тест ни разу не обнаружил ошибки за все время тестирования Когда тест обнаруживает такие же ошибки, как и другие тесты Марат Ахин (СПбПУ) RT 2016 310 / 359
  • 340.
    Приоритизация регрессионных тестов Проблема№3 Как запускать регрессионные тесты? Взяли имеющийся набор тестов и запустили их Такой подход может не всегда нас устраивать Что мы можем изменить? Марат Ахин (СПбПУ) RT 2016 311 / 359
  • 341.
    Приоритизация регрессионных тестов Мыможем изменить порядок, в котором мы запускаем регрессионные тесты Зачем? Чем раньше мы узнаем о том, что в ПО появилась регрессионная ошибка, тем скорее мы сможем приступить к ее исправлению Часто причиной непрохождения различных (напрямую не связанных друг с другом) тестов является одна и та же ошибка в ПО Иногда время на тестирование является ограниченным, и необходимо найти наибольшее число ошибок с учетом всех ограничений Как мы можем приоритизировать регрессионные тесты? Марат Ахин (СПбПУ) RT 2016 312 / 359
  • 342.
    Приоритизация регрессионных тестов Припомощи интуиции Подход работает, если у Вас хорошая интуиция Кроме интуиции можно использовать имеющийся опыт разработки ПО Марат Ахин (СПбПУ) RT 2016 313 / 359
  • 343.
    Приоритизация регрессионных тестов Наоснове знаний о тестовом покрытии ПО Сперва выполняются тесты, которые имеют наибольшее покрытие ПО Сперва выполняются тесты, которые покрывают более важные компоненты ПО Марат Ахин (СПбПУ) RT 2016 314 / 359
  • 344.
    Приоритизация регрессионных тестов Наоснове истории разработки Приоритет отдается тестам, которые чаще других обнаруживали регрессионные ошибки Первыми выполняются тесты, проверяющие корректность работы наиболее «проблемных» компонентов ПО Марат Ахин (СПбПУ) RT 2016 315 / 359
  • 345.
    Приоритизация регрессионных тестов Случайнымобразом Подход перекликается со случайным ВРТ Если мы можем случайным образом поменять порядок выполнения тестов, то почему бы это не сделать? Марат Ахин (СПбПУ) RT 2016 316 / 359
  • 346.
    Приоритизация регрессионных тестов Наоснове характеристик тестов Первыми выполняются тесты с наименьшим временем выполнения Приоритет отдается тестам, которые наиболее активно работают с окружением программной системы Марат Ахин (СПбПУ) RT 2016 317 / 359
  • 347.
    Анализ результатов регрессионноготестирования Проблема №4 Что делать с результатами регрессионного тестирования? Если все тесты проходят – все хорошо Если тест не проходит – то все зависит от того, по какой причине он не проходит Варианты? Марат Ахин (СПбПУ) RT 2016 318 / 359
  • 348.
    Регрессионное тестирование напрактике Как обстоит дело с РТ/ВРТ на практике? Марат Ахин (СПбПУ) RT 2016 319 / 359
  • 349.
    Регрессионное тестирование напрактике РТ используется очень часто TDD Agile Development RUP ВРТ практически не используется Почему? Марат Ахин (СПбПУ) RT 2016 320 / 359
  • 350.
    Регрессионное тестирование напрактике Крайняя сложность выбора регрессионных тестов Опасность пропустить регрессионную ошибку при использовании небезопасного ВРТ Страх перед использованием «непонятной» технологии Простота экстенсивного пути решения проблем РТ Марат Ахин (СПбПУ) RT 2016 321 / 359
  • 351.
    Регрессионное тестирование напрактике Отсутствие хорошей инструментальной поддержки Test impact analysis Chianti Jimpa ... Какие еще сложности связаны с ВРТ? Марат Ахин (СПбПУ) RT 2016 322 / 359
  • 352.
    Регрессионное тестирование напрактике Недетерминизм в тестах Если выполнение тестов может отличаться от запуска к запуску — все плохо Почему? Эффект «лавины» Пропущенный тест в ВРТ может дальше привести к каскадному пропуску множества тестов Что делать? Марат Ахин (СПбПУ) RT 2016 323 / 359
  • 353.
  • 354.
    Дебаггинг Software Testing 101 МаратАхин Санкт-Петербургский политехнический университет 2016 Марат Ахин (СПбПУ) DBG 2016 325 / 359
  • 355.
  • 356.
  • 357.
    Содержание 1 Прелюдия 2 Тестированиеза 45 минут 3 Тестирование в процессе разработки ПО 4 Проблема тестовых входных данных 5 Проблема неявных входных данных 6 Разработка через тестирование 7 Интеграционное тестирование 8 Проблема наблюдаемости Марат Ахин (СПбПУ) DBG 2016 328 / 359
  • 358.
    Поиск ошибок Debugging Процесс поискаошибок в программе Edsger Dijkstra If debugging is the process of removing bugs, then programming must be the process of putting them in. Марат Ахин (СПбПУ) DBG 2016 329 / 359
  • 359.
    Поиск ошибок Как найтиошибку? Запустить тест Тест выполнит фрагмент кода с ошибкой Это вызовет порчу состояния программы Результат работы программы будет некорректным Марат Ахин (СПбПУ) DBG 2016 330 / 359
  • 360.
    Поиск ошибок Как найтиошибку? Запустить тест Тест выполнит фрагмент кода с ошибкой Это вызовет порчу состояния программы Результат работы программы будет некорректным Марат Ахин (СПбПУ) DBG 2016 330 / 359
  • 361.
    Поиск ошибок Как найтиошибку? Запустить тест Тест выполнит фрагмент кода с ошибкой Это вызовет порчу состояния программы Результат работы программы будет некорректным Марат Ахин (СПбПУ) DBG 2016 330 / 359
  • 362.
    Поиск ошибок Как найтиошибку? Запустить тест Тест выполнит фрагмент кода с ошибкой Это вызовет порчу состояния программы Результат работы программы будет некорректным Марат Ахин (СПбПУ) DBG 2016 330 / 359
  • 363.
    Поиск ошибок Как найтиошибку? Запустить тест Тест выполнит фрагмент кода с ошибкой Это вызовет порчу состояния программы Результат работы программы будет некорректным Марат Ахин (СПбПУ) DBG 2016 330 / 359
  • 364.
    Поиск ошибок Если мырешили проблему наблюдаемости... Debugging не нужен Assertions Журнал выполнения Если наблюдаемости не хватает??? Марат Ахин (СПбПУ) DBG 2016 331 / 359
  • 365.
    Основная проблема Основная проблема Наблюдениеза состоянием программы Марат Ахин (СПбПУ) DBG 2016 332 / 359
  • 366.
    Debuggers Debugger to therescue! Две основные задачи отладчика Пошаговое выполнение программы Наблюдение за внутренним состоянием программы Как они это делают? Марат Ахин (СПбПУ) DBG 2016 333 / 359
  • 367.
    Debuggers Тесная интеграция сосредой выполнения Понимание того, что такое инструкция Возможность останавливать выполнение в произвольные моменты времени Знание модели памяти Способность модифицировать выполняемый код ... Марат Ахин (СПбПУ) DBG 2016 334 / 359
  • 368.
    Процесс отладки Дубль №1 1Выдвигаем гипотезу о месте возникновения ошибки 2 Настраиваем отладчик на анализ выбранного фрагмента кода 3 Запускаем программу на выполнение 4 Возможные варианты 1 Ошибка найдена 2 Гипотеза не подтвердилась Если все же не нашли? Марат Ахин (СПбПУ) DBG 2016 335 / 359
  • 369.
    Процесс отладки Дубль №2 1Выдвигаем другую гипотезу о месте возникновения ошибки 2 Настраиваем отладчик на анализ выбранного фрагмента кода 3 Запускаем программу на выполнение 4 Возможные варианты 1 Ошибка найдена 2 Гипотеза не подтвердилась Если все равно не нашли? Марат Ахин (СПбПУ) DBG 2016 336 / 359
  • 370.
    Процесс отладки Дубль №3 1Выдвигаем еще одну гипотезу о месте возникновения ошибки 2 Настраиваем отладчик на анализ выбранного фрагмента кода 3 Запускаем программу на выполнение 4 Возможные варианты 1 Ошибка найдена 2 Гипотеза не подтвердилась А если... Марат Ахин (СПбПУ) DBG 2016 337 / 359
  • 371.
  • 372.
    Много ручного труда Надочто-то с этим делать! Марат Ахин (СПбПУ) DBG 2016 339 / 359
  • 373.
    One step forward,two steps back... Гипотезы обычно раскручиваются в обратном порядке vs Выполнение программы идет в прямом порядке Марат Ахин (СПбПУ) DBG 2016 340 / 359
  • 374.
    Step back Марат Ахин(СПбПУ) DBG 2016 341 / 359
  • 375.
    Time-traveling debugging Отладка свозможностью выполнения программы в обратную сторону Возможность детального исследования поведения программы Нет необходимости перезапускать программу Как это можно сделать? Марат Ахин (СПбПУ) DBG 2016 342 / 359
  • 376.
    Time-traveling debugging Обратные функции Трассировка Записьсостояния памяти (memory snapshots) Не все так просто... Марат Ахин (СПбПУ) DBG 2016 343 / 359
  • 377.
    Неявные входные данные Дата/время Внешнеесостояние (БД, сериализованные данные, и т.д.) Работа с аппаратурой Взаимодействие с другими программами Чем больше неявных данных мы хотим учитывать, тем сложнее это сделать эффективно Марат Ахин (СПбПУ) DBG 2016 344 / 359
  • 378.
    Time-traveling debugging В самомплохом случае – полная запись всей трассы выполнения Значение каждой переменной в каждый момент времени Марат Ахин (СПбПУ) DBG 2016 345 / 359
  • 379.
    Time-traveling virtual machine Чтоеще можно сделать? Все то же самое, но на уровне виртуальной машины Запись взаимодействия ПО с аппаратурой Возможность отладки целого ансамбля программ Никаких проблем с неявными входными данными Марат Ахин (СПбПУ) DBG 2016 346 / 359
  • 380.
    Time-traveling virtual machine Memorysnapshots Запись источников недетерминизма Пользовательский ввод Сетевое взаимодействие Прерывания TTVM позволяют отладить ошибки даже в ОС Марат Ахин (СПбПУ) DBG 2016 347 / 359
  • 381.
    Time travel Марат Ахин(СПбПУ) DBG 2016 348 / 359
  • 382.
    Дихотомия Как поймать африканскогольва? Разделить Африку на две части стеной Лев находится в одной из двух частей Разделить часть со львом на две новой стеной ... PROFIT! Марат Ахин (СПбПУ) DBG 2016 349 / 359
  • 383.
    Дихотомия в отладке Аможно ли то же самое сделать с тестом? А можно ли это сделать автоматически? Марат Ахин (СПбПУ) DBG 2016 350 / 359
  • 384.
    Delta debugging Способ автоматическойминимизации теста Дано: T = {Ci } : P(T) → fail Найти: DD = min{Cj } ⊂ T : P(DD) → fail Что такое Ci ? Что такое min{Cj }? Марат Ахин (СПбПУ) DBG 2016 351 / 359
  • 385.
    Delta debugging Ci –это... Строка в файле Вызов метода Тэг в XML Один байт данных Коммит в VCS Выбирается индивидуально в каждом конкретном случае Марат Ахин (СПбПУ) DBG 2016 352 / 359
  • 386.
    Delta debugging DD =min{Cj } : ∀C ∈ DD P(DD C) → pass Удаление любого компонента из минимального теста приводит к исчезновению ошибки Чем меньше тест, тем проще его анализировать Марат Ахин (СПбПУ) DBG 2016 353 / 359
  • 387.
    Минимизация теста Субоптимальный способ Дихотомия 1:function DD(CC) 2: L = {CC1, . . . , CC|CC|/2} 3: R = {CC|CC|/2+1, . . . , CC|CC|} 4: if only P(L) → fail then 5: return DD(L) 6: else if only P(R) → fail then 7: return DD(R) 8: else 9: return CC 10: end if 11: end function Марат Ахин (СПбПУ) DBG 2016 354 / 359
  • 388.
    Минимизация теста «Оптимальный» способ Полныйперебор 1: function DD(CC) 2: CC = CC {CCi } 3: if P(CC ) → fail then 4: return DD(CC ) 5: else if P(CC ) → pass then 6: return CCi ∪ DD(CC ) 7: end if 8: end function Марат Ахин (СПбПУ) DBG 2016 355 / 359
  • 389.
    Минимизация теста Оптимальный способ Умныйперебор 1: function DD(CC, N) 2: CC = CC1 ∪ . . . ∪ CCN 3: for all CCi do 4: if P(CCi ) → fail then 5: return DD(CCi ) 6: else if P(CC CCi ) → fail then 7: return DD(CC CCi ) 8: end if 9: end for 10: return DD(CC, 2 × N) 11: end function Марат Ахин (СПбПУ) DBG 2016 356 / 359
  • 390.
    Delta debugging напрактике Готовых средств для delta debugging над данными нет Зависимость Ci от типа данных Разные проекты могут накладывать дополнительные ограничения git/hg bisect Марат Ахин (СПбПУ) DBG 2016 357 / 359
  • 391.
  • 392.