Тестирование
Тестирование
❌ Тестирование представляет собой процесс, демонстрирующий отсутствие ошибок в программе
❌ Цель тестирования – показать, что программа корректно исполняет предусмотренные функции
❌ Тестирование – это процесс, позволяющий убедиться в том, что программа выполняет свое назначение
✅ Тестирование – это процесс, исследования, испытания ПО, имеющий следующие цели:
продемонстрировать, что программа соответствует требованиям
выявить ситуации, в которых поведение программы является неправильным, нежелательным (или не соответствующим требованиям)
Тестирование программ можно использовать для того, чтобы показать наличие ошибок, и никогда — для того чтобы показать их отсутствие. (с) Эдсгер Дейкстра
Тестирование – процесс выявления фактов расхождений с требованиями (ошибок). Отладка = Тестирование + Поиск ошибок + Исправление
Кто и зачем тестирует?
Разработчики
Обеспечение качества разработки
студенты
Тестировщики
Обеспечение надежности работы ПО, проверка качества
студенты
Заказчик
Проверка соответствия требований
преподаватели
Пользователи
Обнаружение вариантов использования, которые не были предусмотрены при разработке
преподаватели
Полное тестовое покрытие
Можно ли протестировать всю программу? Для того, чтобы проверить все:
Проверить все возможные данные всех переменных
Проверить все комбинации ввода на все комбинации переменных
Проверить все пути работы программы
Проверить все аппаратные и программные конфигурации
Проверить все возможные способы использования программы любым пользователем
Всегда времени намного меньше, чем требуется… Как доказать или проверить, что в программе реально нет ошибок?
Так надо ли вообще тестировать?

Стоимость исправления ошибок

Пример катастрофы: Ariane 5 – ошибка модуля управления
Ошибки, дефекты (баги, bugs)

Bug – отклонение фактического результата от ожидаемого. Выделяют:
синтаксические ошибки (errors). Делающие компиляцию невозможной:
отсутствие или несоответствие открывающей и закрывающей скобок;
предупреждения (warnings) компилятора. В этом случае компилятор может заметить, что программист делает что-то необычное (вероятно неверное), и сообщает об этом, однако программист сам принимает решение игнорировать сообщение или нет:
использование неинициализированной переменной;
ошибки времени исполнения:
выход за границы выделенной памяти
смысловые ошибки (семантические)
вычитание переменных вместо сложения.
Тестирование и разработчики
Какие тесты пишут разработчики?
Большая часть разработчиков использует ручное тестирование. Если вы что-то сделали, прежде всего, нужно убедиться, что это действительно работает, проверить входные данные и переменные и получить какой-то фидбек. Модульные тесты — проверка, правильно ли работает каждый кусочек кода. Пример: в отдельном файле с тестами вы вызываете каждую свою функцию и подаёте ей какие-то данные на вход и проверяете результат.
Затем идут тесты, с помощью мы проверяем отдельные фичи, связки наших модулей/классов и так далее - интеграционные тесты. Пример: вызывается несколько функций подряд, где результат работы одной функции подаётся на вход другой или проверяется результат работы ряда функций/классов, реализующих определённую фичу.
End-to-end тестирование. Проверка какой-либо фичи с точки зрения клиента и от начала до конца. Пример: тесты, запускаемые на Github, проверяют, правильный ли результат возвращяет ваша программа (не отдельная функция, а вся совокупность классов и функций).
Как тестируют разработчики?
Читают ТЗ /* не всегда до конца правда… */
Проводят ручные тесты
Проверяют потребление ресурсов (памяти)
Замеряют время работы отдельных функций
Вручную проверяют работу программы / функций путём запуска программы с определёнными параметрами
Пишут и запускают автотесты
Пишут скрипт на bash / python (или любой другой знакомый им ЯП)
Используют подключаемые библиотеки и framework для тестирования (Google Test, Catch2 и многое другое)
Запускают автотесты в репозиториях курса, если преподаватели им настроили и читают логи
Ручные vs Авто-тесты
Если вы не знаете, стоит ли тратить время, запариваться и писать тесты самим, то ответьте себе на следующие вопросы:
Является ли сценарий автоматизируемым?
Да, при небольших затратах (для вас)
Да, потребуется существенные затраты
Нет, сценарий невозможно автоматизировать
Насколько важным является данный сценарий?
Требуется проверять его при любых обстоятельствах
Надо регулярно проверять
Нужно проверить пару раз
Варианты ответов:
1-1 – автоматизируйте
1-2 или 2-1 рекомендуется автоматизировать
2-2 стоит сильно подумать надо ли вкладывать средства в автоматизацию
3-* или *-3 нецелесообразно
Методы поиска ошибок
Классификация тестирования в виде ящиков интересна нам тем, что разработчик смотрит на собственный код как на белый ящик. А тестировщик и заказчик рассматривают программу как черный ящик — они до конца не понимают, как именно работает программа, знают только, какие фичи важны и должны работать обязательно.
Баг на сайте интернет-магазина, из-за которого какой-то товар не попадает в корзину, для разработчика — минорная проблема. Достаточно что-то закоммитить и раскоммитить, поменять переменные в одном месте — и все отлично заработает. Для тестировщика и тем более заказчика такой баг оказывается критическим, поскольку не позволяет клиенту купить нужный товар.
Но самый интересный ящик — серый. С ним работают "умные" тестировщики, которые глубоко вникают в код и то, как работает продукт. Сами разработчики также могут выступать в роли таких "умных" тестировщиков, когда смотрят код, над которым не работали, но знают инфрастуктуру и зачем этот код, как он должен работать.

Черный ящик (разработчики)

Белый ящик (заказчики, пользователи)

Разработка тестов
Где искать тесты?
Тщательное изучение и анализ требований: описания функции, модуля, спецификации ...
Декомпозиция требований\функций: разложение задачи на отдельные компоненты (классы, функции)
Выявление всех условий, входных и выходных данных: анализ возможных комбинаций входных данных
Использование накопленных знаний: опыт, который вырабатывается в ходе выполненния других работ
Интуиция: жизненный опыт, основанный на знаниях из других областей
Анализ текущих тестов: просмотр выявленных тестов и добавление новых
Проблемы, которые придется решить
Искать все ошибки или грубейшие?
Зависит от требований к заданию, ресурсов (времени и сил), умений и навыков, желаемые баллы по работе
Если не все, то как установить порог допустимости ошибки?
Приоритизировать требования к работе, оценить оставшиеся время и силы, понять - можно ли получить в текущих условиях больше баллов и что для этого нужно сделать, приоритизировать возможности
Что делать, если сроки поджимают и/или нет ресурсов на дальнейшее тестирование?
Выбрать наиболее приоритеные возможности: лучше поправить ошибки работы с памятью, чем гнаться за максимумом по тестам
Техники обнаружения тестов: классы эквивалентности (partitioning, equivalent analysis)
Класс эквивалентности — одно или несколько значений ввода, к которым программное обеспечение применяет одинаковую логику. Анализируем входные и выходные данные:
правильные классы эквивалентности – корректные (positive) входные данные
неправильные классы эквивалентности – ошибочные (negative) входные данные
Классы эквивалентности. Шаги
Определить классы эквивалентности. Это главный шаг техники, т.к. во многом от него зависит эффективность её применения.
Выбрать одного представителя от каждого класса эквивалентности. На этом этапе следует выбрать один тест из эквивалентного набора тестов.
Выполнение тестов. На этом шаге следует выполнить тесты от каждого класса эквивалентности.
Классы эквивалентности. Пример
Результат: сообщение об ошибке
Результат: печать “Hello”
Результат: сообщение об ошибке
INPUT < 10 Результат: сообщение об ошибке
Программа не принимает числовые значения как факт Проверяется любым числом
10 <= INPUT < 25 Результат: печать “Hello”
Написали <= 25 вместо < 25 Определяется только на границе
25 <= INPUT Результат: сообщение об ошибке
Опечатка: написали 52 вместо 25 Определяется и на границе в том числе
Граничное значение проверяет все 3 типа ошибок Значение не на границе проверяет только 1 тип ошибок
Техники обнаружения тестов: Анализ граничных значений (Boundary Value Testing)
Идентифицировать граничные значения для каждого входного значения (класса эквивалентности)
на границе
значение, меньшее граничного («у границы»\’below point’)
значение, большее граничного («за границей» \’above point’)
Анализ граничных значений. Пример 1
Область корректных значений: [-1.0, 1.0] тесты для -1.0, 1.0, -1.001, 1.001 Максимальная длина слова – 5 символов тесты для 4,5,6 Область выходных значений: минимум расхода 0.00, максимум 2000 подбираем входные данные для того, чтобы получить на выходе 0.00, 2000.00, 2000.01, -0.01
Анализ граничных значений. Пример 2
Для точки: Z (Z - целое число)?
Для отрезка: [x, y]?
Для отрезка: (x, y)?
Как именно тестировать?
Классы эквивалентности: некорректные значения Тестировать одно некорректное значение за раз для того, чтобы проверить, что система идентифицирует его корректно.
Классы эквивалентности: корректные значения Как?... :
провести мозговой штурм с коллегами: накидать идеи и затем вместе сесть и оценить каждое из них на причастность к вашей работе
перебрав все возможные комбинации входных и выходных значений и убрав лишние: один и тот же результат, не зависящий от части входных данных
описав таблицы переходов: фиксация определённых состояний переменных или программы в целом и построение конечного автомата
проанализировав "сценарии использования" вашей программы: что может подать пользователь вашей программе, как от этого зависит её поведение и соответствует ли оно требованиям
используя "метод предположение об ошибке": перечислить в некотором списке возможные ошибки или ситуации, в которых они могут появиться, а затем на основе этого списка сформировать тесты
применить "тестирование, основанное на требованиях": проверяем каждое требование\запрос, которое описано или озвучено
отправить на ревью: преподавателю, а не своему другу/однокурснику!
Last updated