Как научиться искать баги — Серьезность и приоритет — Алгоритм действий — Лучшие практики — Шпаргалка
Типы багов:
- Функциональные
- Синтаксические
- Логические
- Производительности
- Ошибки вычислений
- Безопасности
- Уровня модуля
- Интеграционные баги
- Юзабилити-баги
- Потока управления
- Совместимости
Функциональные
Каждая программа должна работать корректно, то есть делать то что нужно. Как можно понять из названия, функциональные баги — это когда программа не делает нужное.
Могут быть самыми разнообразными, начиная с бага в простой нечасто используемой функции, типа неработающей кнопки “Связаться” где-то в углу, и до полной неработоспособности всего приложения или сайта.
Еще пример: функция кнопки “Сохранить” заключается в том, что она сохраняет внесенные изменения в документе. Если изменения при нажатии кнопки не сохраняются, это функциональный баг.
Поиском багов этого типа занимается функциональное тестирование — отдельная важная сфера в QA (мини-гайд по ссылке).
Синтаксические баги
Ошибка в коде программы. Вероятно, самая частая ошибка, статистически. Случается обычно по невнимательности. Заключается, например, в неправильном/пропущенном символе, неправильно прописанной команде, или пропущенной скобке.
Логические ошибки
Коварная ошибка, труднее выявляемая. Приложение выдает неправильный вывод, или вообще падает.
Логические дефекты это например бесконечные циклы или некорректные переходы, допущенные разработчиком по неопытности или незнанию синтаксиса, вызывающие сложно определяемые ошибки в user flow (“маршруте пользователя по приложению” в процессе пользования им).
Бесконечные циклы — больное место тестировщика, так же как утечки памяти, проблемы с типами данных во многих языках, с компилятором в С++ или сборщиком мусора в Java. Несоблюдение хороших практик в программировании и недостаток опыта у разработчиков добавляют задач QA-отделу.
Еще примеры: переменной присвоено некорректное значение; деление чисел вместо умножения, и т.п.
Подробнее о логических ошибках.
Проблемы производительности
Такие ошибки влияют на скорость, на стабильность, на время отклика, или на потребление ресурсов, из-за чего их находят довольно быстро. Чаще их находят сами разработчики, а не тестировщики. Очень распространенный тип багов.
Ошибки вычислений
Когда приложение выдает некорректное значение пользователю или другой программе.
- Когда в приложении применен некорректный, неподходящий алгоритм
- Несоответствие типа данных
Уязвимости в безопасности
Дефекты в системе безопасности, видимо, наиболее опасные из тех, с которыми сталкивается junior QA. Они “компроментируют” весь проект, всю компанию, и разумеется, QA-команду, если она их пропустила.
Баг в безопасности ставит продукт, компанию, и данные клиента под риск потери очень больших денег. Такие ошибки обходятся дороже всего, в плане денег и деловой репутации, что может быть еще хуже.
Самыми частыми, статистически, ошибками безопасности являются: ошибки шифрования; подверженность SQL-инъекциям; XSS-уязвимости; переполнения буфера; логические ошибки в подсистеме безопасности; некорректная аутентификация.
Баги уровня модуля
На уровне отдельного модуля. Принято, чтобы разработчики сами делали юнит-тестирование модулей (им это сделать проще, т.к. они лучше понимают свой код), но в принципе к этому могут привлекать и QA.
Итак, в процессе юнит-тестирования находят ошибки в модулях: чаще всего это (случайные) ошибки вычислений и ошибки в логике, обычно они заметные и легко вылавливаемые. Такие баги хорошо изолируются (потому что они влияют только на небольшую часть кода), и быстро устраняются.
Интеграционные баги
Это ошибки взаимодействия между несколькими подсистемами приложения. Из-за того, что подсистемы чаще написаны разными разработчиками, командами и даже компаниями, интеграционные баги бывают достаточно сложными.
Становятся заметны они, когда например два (или больше) модулей кода ошибочно взаимодействуют, из-за программной несовместимости между ними. Такие баги довольно сложно определить и пофиксить, разработчикам, как правило, приходится переписывать довольно большие объемы кода.
Статистически, это бывают ошибки переполнения памяти, и некорректные взаимодействия между подсистемой пользовательского интерфейса и базами данных.
Юзабилити-баги
Такие дефекты не позволяют пользователю легко и приятно работать с приложением. Например, это проблемы с разметкой контента, его недоступностью, или например чрезмерно усложненная процедура регистрации/входа. К тестированию юзабилити привлекают и разработчиков и тестировщиков, а также, конечно, UX-дизайнеров. Проверяется соблюдение соответствующих гайдлайнов (если они соблюдаются с самого начала, эти ошибки можно предотвратить).
Баги потока управления (Control Flow)
Ошибки Control Flow (потока управления, путей выполнения программы) мешают ей корректно переходить к выполнению следующих задач, то есть корректно “передавать управление”, что стопорит весь workflow компании. Обычно это “мертвый код” (отсутствует вход), или “бесконечный цикл” (отсутствует выход).
Пример: в опроснике пользователь нажимает “Сохранить”, предполагается переход к концу опросника/теста, а перехода к следующей странице не происходит.
Проблемы совместимости (Compatibility issues)
Приложение оказывается несовместимым с неким устройством, целым классом устройств какого-то производителя, или операционной системой. Такие ошибки обычно проявляются довольно поздно в цикле тестирования. Во избежание, проводят тестирование совместимости с наиболее распространенными устройствами (смартфонами) и ОС.
Итак, уже примерно знаем, ЧТО искать, постараемся понять, КАК искать.
Как научиться искать баги
“Быстрая проверка” на реальных устройствах и в браузерах
Трудно идет тестирование, если у тестировщика нет сформулированных требований к софту — потому что трудно написать тестовые сценарии. В такой ситуации можно “атаковать систему”, вводя неправильные значения во все возможные поля. Если баги есть, они обычно проявляются.
Или, оставлять некоторые поля пустыми, перегружать интерфейс запросами, вводить числа там где предполагается ввод букв и наоборот, превышать лимит символов, вводить запрещенные символы, многократно вводить неправильные пароли, и так далее.
Это техника экспресс-анализа системы, позволяющая опытному тестировщику быстро оценить устойчивость системы к багам и примерно количество их, анализируя сообщения об ошибках и характер проявляемых ошибок.
Даже если таким образом будет найдено сравнительно мало багов, логично предположить, что все-таки есть проблемы в основной части функциональности. Отсутствие багов при “экспресс-анализе” (“quick attack”) обычно показывает, что основная часть функциональности более-менее в порядке.
Такая “быстрая атака” должна выполняться в стандартном пользовательском окружении — как можно более близком к тем условиям, в которых будет работать конечный пользователь.
Внимание тестовому окружению
Обычно у тестировщиков есть время на подготовку сценариев, прописывание таймлайна и настройку процедур. А также на подготовку тестовой инфраструктуры, или тестового окружения.
Из-за проблем с плохо подготовленным тестовым окружением возникают задержки в получении результатов тестирования. Проявляются баги, вызванные именно тестовым окружением, а не самим софтом. Мало что так раздражает, как некорректно работающее окружение.
Например, тестировщик нашел и отрепортил баг, а когда разработчик проверил его, в коде проблем не нашел, потому что проблема была с окружением. От этого возникает задержка.
Проблемы с окружением часто вызывают нестабильность тестов: один и тот же тест при запуске каждый раз выдает разный результат. Это не позволяет воспроизвести баг.
Тщательное исследование
Перед началом тестирования нужно внимательно изучить приложение или тестируемый модуль.
Подготовить достаточно тестовых данных. Этот датасет должен включать и базы данных, если тестируется приложение, использующее базы данных (а это почти все приложения сейчас).
Полезно вставлять в код своих автотестов указатели (если язык это поддерживает), для облегчения поиска нужных блоков. А также точки останова (брейкпойнты, контрольные точки), останавливающие выполнение в какой-то точке, чтобы точнее определить “место бага”.
Принцип Парето
Согласно этому принципу, 20% усилий дают 80% результата.
А 80% усилий дают лишь 20% результата.
Применительно к QA-индустрии, принцип Парето гласит, что 80% багов сосредоточены в 20% модулей. (Необязательно такое точное соотношение, но в целом). По принципу Парето, большинство багов затаились в одном-двух модулях (или даже еще меньшей части кода).
Если всерьез взяться за эти модули и вычистить из них баги, можно считать работу на 80% сделанной.
Подробно о принципе Парето в тестировании.
Четкие цели
Тестировщик должен учитывать стандарты и лучшие практики и придерживаться их, это даст понимание, какие ошибки искать тщательнее и в первую очередь. Должен понимать логику действий конечного пользователя. Что пользователь ожидает от этого софта? Какой его user experience? Какой функциональности ожидает? На какие баги вообще не обратит внимания, а какие заставят отказаться от приложения?
Четче изложенные цели тестирования помогут писать хорошие тестовые сценарии и тест-кейсы. Если главная функция, “главная потребность пользователя” уточнена и дан приоритет, тестировщик может сначала протестировать эту функцию, а остальные отложить, или поручить стажерам.
Серьезность и приоритет
По серьезности (Severity)
- Блокирующий баг, так называемый “блокер”, который делает абсолютно невозможной дальнейшую работу с приложением. Срочно исправляют.
- Критический баг. “Критикал”. Некорректно работает все приложение, или его важнейший модуль. Тестирование остальных, менее существенных багов прекращается, все силы бросают на фикс такого бага. Сюда входит, например, кейс, когда приложение выдает ошибку сервера при попытке входа в приложение.
- Существенный. “Мажор”. Влияет на ключевую функцию, и приложение ведет себя с отклонением от прописанных требований. Например, email-провайдер не дает добавить больше одного адреса в поле получателя.
- Средней серьезности. “Минор”. Когда не очень важная функция не ведет себя соответственно требованиям. Например, ссылка в “Условиях использования” продукта ведет в никуда.
(Перечисленные выше баги коротко обозначаются S1, S2, S3, S4 по серьезности.)
- Низкой серьезности. “Тривиал”. Обычно это небольшие дефекты пользовательского интерфейса. Например, кнопки, которые должны быть одинаковыми, немножко отличаются по цвету и размеру.
По приоритету
Срочные. (Топ-приоритет, ургентный, безотлагательный). Должны быть устранены в 24 часа после получения репорта. Обычно это блокеры и критикалы. Но такой приоритет могут получить и дефекты с низкой серьезностью. Например, опечатка в названии компании на главной странице сайта никак не ухудшает функциональность, однако имеет сильнейшее негативное влияние на имидж компании, поэтому это срочный баг.
Приоритеты выставляются менеджером проекта:
Высокий приоритет. Это ошибки, которые должны быть устранены до релиза, согласно критериям завершения тестирования (exit-criteria). Например, это ошибка, несмотря на корректность всех введенных данных мешающая переходу со страницы входа на главную.
Средний приоритет. Должны быть устранены до релиза или сразу после релиза. Это например дефект, не нарушающий требования, но некорректно отображающий контент в одном из браузеров.
Низкий приоритет. Их можно не фиксить, и критериям завершения это не противоречит, но такие дефекты надо устранить до финального релиза. Обычно это опечатки, небольшие дефекты в дизайне (например выравнивание текста), не очень заметные ошибки в размере элементов, и прочие “косметические” дефекты.
(Перечисленные выше баги обозначаются P1, P2, P3 от высокого к низкому.)
Также баги классифицируют по частоте проявления, от высокой до очень низкой (4 степени).
Подробнее о серьезности и приоритете, а также о глобальном приоритете и частоте багов.
Стандартный порядок действий при обнаружении бага
- Проверить дополнительные (связанные) вещи
Обычно баги “по одному не ходят”, то есть где-то поблизости есть аналогичные, или связанные с уже найденными.
- Зафиксировать текущее состояние приложения
Состояние приложения и состояние окружения. Это поможет примерно определить причину бага — внутренняя или внешняя, и воспроизвести баг.
- Проверить, может баг уже есть в репортах
Чтобы не делать уже сделанную кем-то работу.
- Репорт
Теперь надо написать классный баг-репорт, не затягивая время — это сокращает цикл фидбека между написанием кода и валидацией.
Статусы багов (в жизненном цикле)
- Открыт (добавлен в репорт)
- В работе (принят к исправлению)
- Исправлен (и передан на перепроверку)
- Закрыт (уже не воспроизводится)
также дополнительно:
- Отклонен (ошибка в репорте)
- Отсрочен (как неприоритетный)
- Переоткрыт (после двух предыдущих статусов)
Подробнее о системах контроля багов — здесь
Лучшие практики
- Сначала хорошо исследовать и понять приложение (модуль)
- Создать специальные тест-кейсы, а именно функциональные тест-кейсы, посвященные критически важным функциям
- Подготовить достаточно тестовых данных
- Запустить тесты снова, в другом тестовом окружении
- Сравнивать полученные результаты с ожидаемыми
- Проанализировать тестовый сет, используя старые тестовые данные
- Выполнить стандартные тест-кейсы, которые ранее показывали себя надежными. Например, если тестировалось поле ввода для стандартного текста, ввести HTML-теги и проверить, что получится
- После завершения большей части тестов, если есть усталость, отдохнуть, занявшись обезьяньим тестированием (monkey testing)
Тестирование на реальных девайсах и в реальных окружениях
Тестирование в реальных окружениях является хорошей практикой в QA, а в тестировании мобильных приложений — обязательной практикой. Реальное окружение быстрее “апгрейдит” тестировщика. Но оно требует закупки/аренды довольно-таки внушительного парка устройств. Вообще, тестирование всех возможных комбинаций браузер/ОС/девайс — отдельная головная боль. Здесь помогают облачные платформы.
***
Шпаргалка QA Trainee/Junior
Серьезность бага
- Blocker
- Critical
- Major
- Minor
- Trivial
Приоритет
- Top
- High
- Normal
- Low
Типы багов
- Функциональные
- Синтаксические
- Логические
- Производительности
- Ошибки вычислений
- Безопасности
- Уровня модуля
- Интеграционные баги
- Юзабилити-баги
- Потока управления
- Совместимости
Частота бага
- Высокая
- Средняя
- Низкая
- Очень низкая
Статус бага
- Открыт
- В работе
- Исправлен
- Закрыт
- Отклонен
- Отсрочен
- Переоткрыт
Что делает тестировщик, когда находит баг
- Проверяет связанные или аналогичные вещи
- Фиксирует текущее состояние приложения и тестового окружения
- Проверяет, нет ли этого бага в репорте
- Пишет репорт
***
Пять технических и пять нетехнических навыков хорошего QA
Регрессионное тестирование: подборка инструментов
Эмуляторы и симуляторы: в чем разница
Дефекты программного обеспечения можно обнаружить на каждом этапе разработки и тестирования продукта. Чтобы гарантировать исправление наиболее серьезных дефектов программного обеспечения, тестировщикам важно иметь хорошее представление о различных типах дефектов, которые могут возникнуть.
В этой статье мы обсудим самые распространенные типы ПО дефекты и способы их выявления.
Что такое дефект?
Дефект программного обеспечения — это ошибка, изъян, сбой или неисправность в компьютерной программе, из-за которой она выдает неправильный или неожиданный результат или ведет себя непреднамеренным образом. Программная ошибка возникает, когда фактические результаты не совпадают с ожидаемыми. Разработчики и программисты иногда допускают ошибки, которые создают ошибки, называемые дефектами. Большинство ошибок возникает из-за ошибок, которые допускают разработчики или программисты.
Обязательно прочтите: Разница между дефектом, ошибкой, ошибкой и сбоем
Типы программных ошибок при тестировании программного обеспечения
Существует множество различных типов дефектов программного обеспечения, и тестировщикам важно знать наиболее распространенные из них, чтобы они могут эффективно тестировать их.
Ошибки программного обеспечения подразделяются на три типа:
- Дефекты программного обеспечения по своей природе
- Дефекты программного обеспечения по их приоритету
- Дефекты программного обеспечения по их серьезности
Обычно мы можем видеть приоритет и серьезность классификаторов в большинстве инструментов отслеживания ошибок. Если мы настроим классификатор в соответствии с характером ошибки, а также приоритетом и серьезностью, это поможет легко управлять распределением обязанностей по исправлению ошибок соответствующим командам.
#1. Дефекты программного обеспечения по своей природе
Ошибки в программном обеспечении имеют широкий спектр природы, каждая из которых имеет свой собственный набор симптомов. Несмотря на то, что таких багов много, сталкиваться с ними можно не часто. Вот наиболее распространенные ошибки программного обеспечения, классифицированные по характеру, с которыми вы, скорее всего, столкнетесь при тестировании программного обеспечения.
#1. Функциональные ошибки
Как следует из названия, функциональные ошибки — это те, которые вызывают сбои в работе программного обеспечения. Хорошим примером этого может служить кнопка, при нажатии на которую должно открываться новое окно, но вместо этого ничего не происходит.
Функциональные ошибки можно исправить, выполнив функциональное тестирование.
#2. Ошибки на уровне модуля
Ошибки на уровне модуля — это дефекты, связанные с функциональностью отдельного программного модуля. Программный модуль — это наименьшая тестируемая часть приложения. Примеры программных модулей включают классы, методы и процедуры. Ошибки на уровне подразделения могут существенно повлиять на общее качество программного обеспечения.
Ошибки на уровне модуля можно исправить, выполнив модульное тестирование.
#3. Ошибки уровня интеграции
Ошибки уровня интеграции — это дефекты, возникающие при объединении двух или более программных модулей. Эти дефекты может быть трудно найти и исправить, потому что они часто требуют координации между несколькими командами. Однако они могут оказать существенное влияние на общее качество программного обеспечения.
Ошибки интеграции можно исправить, выполнив интеграционное тестирование.
#4. Дефекты юзабилити
Ошибки юзабилити — это дефекты, влияющие на работу пользователя с программным обеспечением и затрудняющие его использование. Дефект юзабилити — это дефект пользовательского опыта программного обеспечения, который затрудняет его использование. Ошибки юзабилити — это такие ошибки, как если веб-сайт сложен для доступа или обойти, или процесс регистрации сложен для прохождения.
Во время тестирования удобства использования тестировщики программного обеспечения проверяют приложения на соответствие требованиям пользователей и Руководству по доступности веб-контента (WCAG) для выявления таких проблем. Однако они могут оказать существенное влияние на общее качество программного обеспечения.
Ошибки, связанные с удобством использования, можно исправить, выполнив тестирование удобства использования.
#5. Дефекты производительности
Ошибки производительности — это дефекты, влияющие на производительность программного обеспечения. Это может включать в себя такие вещи, как скорость программного обеспечения, объем используемой памяти или количество потребляемых ресурсов. Ошибки уровня производительности сложно отследить и исправить, поскольку они могут быть вызваны рядом различных факторов.
Ошибки юзабилити можно исправить, выполнив тестирование производительности.
#6. Дефекты безопасности
Ошибки безопасности — это тип дефекта программного обеспечения, который может иметь серьезные последствия, если его не устранить. Эти дефекты могут позволить злоумышленникам получить доступ к конфиденциальным данным или системам или даже позволить им получить контроль над уязвимым программным обеспечением. Таким образом, очень важно, чтобы ошибкам уровня безопасности уделялось первоочередное внимание и устранялись как можно скорее.
Ошибки безопасности можно исправить, выполнив тестирование безопасности.
#7. Дефекты совместимости
Дефекты совместимости — это те ошибки, которые возникают, когда приложение несовместимо с оборудованием, на котором оно работает, или с другим программным обеспечением, с которым оно должно взаимодействовать. Несовместимость программного и аппаратного обеспечения может привести к сбоям, потере данных и другому непредсказуемому поведению. Тестировщики должны знать о проблемах совместимости и проводить соответствующие тесты. Программное приложение, имеющее проблемы с совместимостью, не работает последовательно на различных видах оборудования, операционных системах, веб-браузерах и устройствах при подключении к определенным программам или работе в определенных сетевых условиях.
Ошибки совместимости можно исправить, выполнение тестирования совместимости.
#8. Синтаксические ошибки
Синтаксические ошибки являются самым основным типом дефекта. Они возникают, когда код нарушает правила языка программирования. Например, использование неправильной пунктуации или забывание закрыть скобку может привести к синтаксической ошибке. Синтаксические ошибки обычно мешают запуску кода, поэтому их относительно легко обнаружить и исправить.
#9. Логические ошибки
Логические ошибки — это дефекты, из-за которых программа выдает неправильные результаты. Эти ошибки может быть трудно найти и исправить, потому что они часто не приводят к каким-либо видимым ошибкам. Логические ошибки могут возникать в любом типе программного обеспечения, но они особенно распространены в приложениях, требующих сложных вычислений или принятия решений.
Общие симптомы логических ошибок включают:
- Неверные результаты или выходные данные
- Неожиданное поведение
- Сбой или зависание программного обеспечения
Чтобы найти и исправить логические ошибки, тестировщикам необходимо иметь четкое представление о коде программы и о том, как она должна работать. Часто лучший способ найти такие ошибки — использовать инструменты отладки или пошаговое выполнение, чтобы отслеживать выполнение программы и видеть, где что-то идет не так.
#2. Дефекты программного обеспечения по степени серьезности
Уровень серьезности присваивается дефекту по его влиянию. В результате серьезность проблемы отражает степень ее влияния на функциональность или работу программного продукта. Дефекты серьезности классифицируются как критические, серьезные, средние и незначительные в зависимости от степени серьезности.
#1. Критические дефекты
Критический дефект — это программная ошибка, имеющая серьезные или катастрофические последствия для работы приложения. Критические дефекты могут привести к сбою, зависанию или некорректной работе приложения. Они также могут привести к потере данных или уязвимостям в системе безопасности. Разработчики и тестировщики часто придают первостепенное значение критическим дефектам, поскольку их необходимо исправить как можно скорее.
#2. Серьезные дефекты
Серьезный дефект — это программная ошибка, существенно влияющая на работу приложения. Серьезные дефекты могут привести к замедлению работы приложения или другому неожиданному поведению. Они также могут привести к потере данных или уязвимостям в системе безопасности. Разработчики и тестировщики часто придают первостепенное значение серьезным дефектам, поскольку их необходимо исправить как можно скорее.
#3. Незначительные дефекты
Незначительный дефект — это программная ошибка, которая оказывает небольшое или незначительное влияние на работу приложения. Незначительные дефекты могут привести к тому, что приложение будет работать немного медленнее или демонстрировать другое неожиданное поведение. Разработчики и тестировщики часто не придают незначительным дефектам приоритет, потому что их можно исправить позже.
#4. Тривиальные дефекты
Тривиальный дефект – это программная ошибка, не влияющая на работу приложения. Тривиальные дефекты могут привести к тому, что приложение отобразит сообщение об ошибке или проявит другое неожиданное поведение. Разработчики и тестировщики часто присваивают тривиальным дефектам самый низкий приоритет, потому что они могут быть исправлены позже.
#3. Дефекты программного обеспечения по приоритету
#1. Дефекты с низким приоритетом
Дефекты с низким приоритетом, как правило, не оказывают серьезного влияния на работу программного обеспечения и могут быть отложены для исправления в следующей версии или выпуске. В эту категорию попадают косметические ошибки, такие как орфографические ошибки, неправильное выравнивание и т. д.
#2. Дефекты со средним приоритетом
Дефекты со средним приоритетом — это ошибки, которые могут быть исправлены после предстоящего выпуска или в следующем выпуске. Приложение, возвращающее ожидаемый результат, которое, однако, неправильно форматируется в конкретном браузере, является примером дефекта со средним приоритетом.
#3. Дефекты с высоким приоритетом
Как следует из названия, дефекты с высоким приоритетом — это те, которые сильно влияют на функционирование программного обеспечения. В большинстве случаев эти дефекты необходимо исправлять немедленно, так как они могут привести к серьезным нарушениям нормального рабочего процесса. Дефекты с высоким приоритетом обычно классифицируются как непреодолимые, так как они могут помешать пользователю продолжить выполнение поставленной задачи.
Некоторые распространенные примеры дефектов с высоким приоритетом включают:
- Дефекты, из-за которых приложение не работает. сбой
- Дефекты, препятствующие выполнению задачи пользователем
- Дефекты, приводящие к потере или повреждению данных
- Дефекты, раскрывающие конфиденциальную информацию неавторизованным пользователям
- Дефекты, делающие возможным несанкционированный доступ к системе
- Дефекты, приводящие к потере функциональности
- Дефекты, приводящие к неправильным результатам или неточным данным
- Дефекты, вызывающие проблемы с производительностью, такие как чрезмерное использование памяти или медленное время отклика
#4. Срочные дефекты
Срочные дефекты — это дефекты, которые необходимо устранить в течение 24 часов после сообщения о них. В эту категорию попадают дефекты со статусом критической серьезности. Однако дефекты с низким уровнем серьезности также могут быть классифицированы как высокоприоритетные. Например, опечатка в названии компании на домашней странице приложения не оказывает технического влияния на программное обеспечение, но оказывает существенное влияние на бизнес, поэтому считается срочной.
#4. Дополнительные дефекты
#1. Отсутствующие дефекты
Отсутствующие дефекты возникают из-за требований, которые не были включены в продукт. Они также считаются несоответствиями спецификации проекта и обычно негативно сказываются на пользовательском опыте или качестве программного обеспечения.
#2. Неправильные дефекты
Неправильные дефекты — это те дефекты, которые удовлетворяют требованиям, но не должным образом. Это означает, что хотя функциональность достигается в соответствии с требованиями, но не соответствует ожиданиям пользователя.
#3. Дефекты регрессии
Дефект регрессии возникает, когда изменение кода вызывает непреднамеренное воздействие на независимую часть программного обеспечения.
Часто задаваемые вопросы — Типы программных ошибок< /h2>
Почему так важна правильная классификация дефектов?
Правильная классификация дефектов важна, поскольку она помогает эффективно использовать ресурсы и управлять ими, правильно приоритизировать дефекты и поддерживать качество программного продукта.
Команды тестирования программного обеспечения в различных организациях используют различные инструменты отслеживания дефектов, такие как Jira, для отслеживания дефектов и управления ими. Несмотря на то, что в этих инструментах есть несколько вариантов классификации дефектов по умолчанию, они не всегда могут наилучшим образом соответствовать конкретным потребностям организации.
Следовательно, важно сначала определить и понять типы дефектов программного обеспечения, которые наиболее важны для организации, а затем соответствующим образом настроить инструмент управления дефектами.
Правильная классификация дефектов также гарантирует, что команда разработчиков сможет сосредоточиться на критических дефектах и исправить их до того, как они повлияют на конечных пользователей.
Кроме того, это также помогает определить потенциальные области улучшения в процессе разработки программного обеспечения, что может помочь предотвратить появление подобных дефектов в будущих выпусках.
Таким образом, отслеживание и устранение дефектов программного обеспечения может показаться утомительной и трудоемкой задачей. , правильное выполнение может существенно повлиять на качество конечного продукта.
Как найти лежащие в основе ошибки программного обеспечения?
Определение основной причины программной ошибки может быть сложной задачей даже для опытных разработчиков. Чтобы найти лежащие в основе программные ошибки, тестировщики должны применять систематический подход. В этот процесс входят различные этапы:
1) Репликация. Первым этапом является воспроизведение ошибки. Это включает в себя попытку воспроизвести тот же набор шагов, в котором возникла ошибка. Это поможет проверить, является ли ошибка реальной или нет.
2) Изоляция. После того, как ошибка воспроизведена, следующим шагом будет попытка ее изоляции. Это включает в себя выяснение того, что именно вызывает ошибку. Для этого тестировщики должны задать себе несколько вопросов, например:
– Какие входные данные вызывают ошибку?
– При каких различных условиях возникает ошибка?
– Каковы различные способы проявления ошибки?
3) Анализ: после Изолируя ошибку, следующим шагом будет ее анализ. Это включает в себя понимание того, почему возникает ошибка. Тестировщики должны задать себе несколько вопросов, таких как:
– Какова основная причина ошибки?
– Какими способами можно исправить ошибку?
– Какое исправление было бы наиболее эффективным? эффективно?
4) Отчет. После анализа ошибки следующим шагом является сообщение о ней. Это включает в себя создание отчета об ошибке, который включает всю соответствующую информацию об ошибке. Отчет должен быть четким и кратким, чтобы разработчики могли его легко понять.
5) Проверка. После сообщения об ошибке следующим шагом является проверка того, была ли она исправлена. Это включает в себя повторное тестирование программного обеспечения, чтобы убедиться, что ошибка все еще существует. Если ошибка исправлена, то тестер может подтвердить это и закрыть отчет об ошибке. Если ошибка все еще существует, тестировщик может повторно открыть отчет об ошибке.
Заключение
В индустрии программного обеспечения дефекты — неизбежная реальность. Однако благодаря тщательному анализу и пониманию их характера, серьезности и приоритета дефектами можно управлять, чтобы свести к минимуму их влияние на конечный продукт.
Задавая правильные вопросы и применяя правильные методы, тестировщики могут помочь обеспечить чтобы дефекты обнаруживались и исправлялись как можно раньше в процессе разработки.
TAG: qa
Баг – дефект, помилка в програмі, що викликає її неправильну і (або) непередбачувану роботу.
Дефекти виявляються на етапі тестування програмного забезпечення, коли тестувальник проводить порівняння отриманих результатів роботи програми (компонента або дизайну) з очікуваним результатом.
Відповідно до видів тестування баги бувають різного походження. Більш узагальнено їх можна поділити на функціональні і нефункціональні. Для ефективного функціонального тестування дуже важливо відрізняти дефекти функціоналу від інших. Розглянемо деякі рекомендації:
- Необхідно визначити, чи є поведінка певної функції нормальною в різних умовах. Протестувати роботу функції самостійно і в поєднанні з іншими функціями для виявлення потенційних відмінностей.
- Визначити можливі варіанти використання системи цільовою аудиторією користувачів, що допоможе визначити побажання до системи.
- Перевірити верстку і контент, так як це може стати функціональним дефектом, якщо вони перешкоджають функціоналу.
- У разі зацікавленості клієнта варто включити в перевірки тестування безпеки.
- Звернути увагу на взаємодію системи зі сторонніми розширеннями браузера або антивірусом. Так як вони можуть блокувати частину контенту або роботу функціонала.
З цього переліку, функціональний дефект – це дефект, пов’язаний з порушенням роботи програмного продукту. Він може бути пов’язаний з логікою самого додатка, окремої функції або системи в цілому.
Залежно від мети, функціональне тестування може проводитися:
- грунтуючись на функціональних вимогах специфікації. Для повного покриття тестами всього функціоналу описуються тестові випадки (test cases). При цьому обов’язково враховується пріоритет функцій. Такий підхід дозволяє перевірити роботу системи при позитивних і негативних сценаріях: введення валідних і невалідних даних, різні комбінації дій і та ін.
- грунтуючись на бізнес-процесах, для проведення яких призначено додаток. Важливо, щоб функціонал системи забезпечував правильність виконання операцій з точки зору сценаріїв використання системи (use cases).
Тестувальнику доводиться працювати з великим об’ємом інформації, вибирати з безлічі варіантів вирішення завдань і винаходити нові. У процесі цієї діяльності важко утримати і структурувати в голові всі перевірки. Тому для ефективного знаходження функціональних багів і найбільш повного покриття тестами далі сформулюємо кілька порад.
- До тестування можна приступати вже з моменту появи перших вимог. Тут доречно складання стратегії тестування, написання чек-лістів, тест-кейсів і та ін. Найчастіше це допомагає усувати велику кількість неточностей, готувати тестове оточення.
Перевірки в чек-лісті найкраще групувати щодо логіки роботи програми, за функціональними модулями системи. Структуру списку перевірок найкраще зробити багаторівневою, це дає змогу побачити ієрархію функцій. Так ймовірність пропустити баг набагато менше. Чек-ліст повинен бути повним, але не надмірним. Не допускайте дублювання (часто з’являється через різні формулювання однієї і тієї ж ідеї).
Приступаючи до написання чек-ліста, задайте собі наступні запитання:
- Що належить тестувати?
Необхідно розуміти яка це система: чітко знати вимоги до її роботи та цільове призначення. - Ким буде кінцевий користувач?
Відповідь забезпечує розуміння і планування характерних сценаріїв використання системи. - Як зазвичай використовується система?
Найкраще розділити основні завдання на більш дрібні підзадачі для складання перевірок позитивного тестування. - Як зламати продукт?
Теж декомпозиція основних завдань, але з метою негативного тестування.
- Систему зі складною структурою і логікою роботи піддавайте функціональній декомпозиції. Розбийте її на прості підзадачі, які будуть більш легкими для запам’ятовування, щоб без зусиль утримати в голові всю інформацію про об’єкт тестування.
- У процесі складання стратегії тестування відзначайте неточності. Нагромаджені питання необхідно уточнити і звернутися до того, хто може надати відповіді.
- Спочатку проводьте позитивні перевірки найважливіших функціональних модулів. Поступово підвищуючи складність перевірок можна переходити до негативних кейсів.
- Застосування технік класів еквівалентності і граничних умов допоможе уникнути дублювання тестів.
- Допускається об’єднання позитивних перевірок, але об’єднання негативних тест-кейсів майже завжди заборонено.
Пошук шляхів для оптимізації початкової стратегії тестування допоможе знизити трудовитрати на її проведення.
Спираючись на ці правила розберемо невелику частину чекліста тестування функціоналу. Перевіримо модуль реєстрації на сайті.
Для форми реєстрації пропонуємо перевірити:
- валідацію всіх обов’язкових полів;
- неприпустимість введення спецсимволів в поля;
- введення букв в числові поля – в цьому випадку має відображатися відповідне повідомлення про помилку;
- валідацію високосних років (чи вік вираховується правильно);
- відображення спливаючого повідомлення: «Це поле обмежене 60 знаками», якщо введені дані перевищують кількість 60 символів в полі «Логін»;
- відображення в потрібній валюті значення вартості передплати;
- функцію завантаження файлу умов згоди;
- функцію відкриття завантаженого документа;
- видалення кукі, перебуваючи на сайті;
- видалення кукі після відвідування сайту;
- функцію перенаправлення користувача на спеціальну сторінку помилки.
З вищесказаного можемо сформулювати висновок: чим повніше покриття системи тестами, тим вище ймовірність знаходження функціональних багів. Сформувати ефективну стратегію тестування і структурувати перевірки допоможе аналіз функцій системи з застосуванням наших рекомендацій.
функциональная ошибка
- функциональная ошибка
-
1) Engineering: functional error
2) Microelectronics: functional fault
Универсальный русско-английский словарь.
.
2011.
Смотреть что такое «функциональная ошибка» в других словарях:
-
ошибка — 01.02.47 ошибка (цифровые данные) [error <digital data>](1)4): Результат сбора, хранения, обработки и передачи данных, при котором бит или биты принимают несоответствующие значения, либо в потоке данных недостает битов. 4)Терминологические… … Словарь-справочник терминов нормативно-технической документации
-
ошибка человека — 3.26 ошибка человека [оператора, пользователя] (human error): Действие человека [оператора, пользователя], приведшее к непреднамеренному результату. Источник: ГОСТ Р 53195.1 2008: Безопасность … Словарь-справочник терминов нормативно-технической документации
-
ГОСТ Р МЭК 61508-4-2007: Функциональная безопасность систем электрических, электронных, программируемых электронных, связанных с безопасностью. Часть 4. Термины и определения — Терминология ГОСТ Р МЭК 61508 4 2007: Функциональная безопасность систем электрических, электронных, программируемых электронных, связанных с безопасностью. Часть 4. Термины и определения оригинал документа: 3.7.4 анализ влияния (impact analysis) … Словарь-справочник терминов нормативно-технической документации
-
ГОСТ Р 53195.1-2008: Безопасность функциональная связанных с безопасностью зданий и сооружений систем. Часть 1. Основные положения — Терминология ГОСТ Р 53195.1 2008: Безопасность функциональная связанных с безопасностью зданий и сооружений систем. Часть 1. Основные положения оригинал документа: 3.1 антропогенная опасность: Опасность, исходящая от людей, вызванная их… … Словарь-справочник терминов нормативно-технической документации
-
Корреляция — (Correlation) Корреляция это статистическая взаимосвязь двух или нескольких случайных величин Понятие корреляции, виды корреляции, коэффициент корреляции, корреляционный анализ, корреляция цен, корреляция валютных пар на Форекс Содержание… … Энциклопедия инвестора
-
Коэффициент корреляции — (Correlation coefficient) Коэффициент корреляции это статистический показатель зависимости двух случайных величин Определение коэффициента корреляции, виды коэффициентов корреляции, свойства коэффициента корреляции, вычисление и применение… … Энциклопедия инвестора
-
отказ — 3.14 отказ: Событие, заключающееся в нарушении работоспособного состояния машины, которое наступает, когда машина утрачивает одну или несколько своих основных функций. Примечание Отказ машины обычно происходит в том случае, когда один или… … Словарь-справочник терминов нормативно-технической документации
-
ГОСТ Р МЭК 62340-2011: Атомные станции. Системы контроля и управления, важные для безопасности. Требования по предотвращению отказов по общей причине — Терминология ГОСТ Р МЭК 62340 2011: Атомные станции. Системы контроля и управления, важные для безопасности. Требования по предотвращению отказов по общей причине оригинал документа: 3.25 валидация (validation): Процесс определения того,… … Словарь-справочник терминов нормативно-технической документации
-
ГОСТ 22670-77: Сеть связи цифровая интегральная. Термины и определения — Терминология ГОСТ 22670 77: Сеть связи цифровая интегральная. Термины и определения оригинал документа: 10. n ичный сигнал электросвязи n агу digital signal Цифровой сигнал электросвязи, имеющий п возможных состояний представляющего параметра,… … Словарь-справочник терминов нормативно-технической документации
-
ГОСТ Р МЭК 61513-2011: Атомные станции. Системы контроля и управления, важные для безопасности. Общие требования — Терминология ГОСТ Р МЭК 61513 2011: Атомные станции. Системы контроля и управления, важные для безопасности. Общие требования оригинал документа: [МАГАТЭ 50 SG D8] Примечание 1 См. также «система, важная для безопасности», «класс систем контроля… … Словарь-справочник терминов нормативно-технической документации
-
ГОСТ 25868-91: Оборудование периферийное систем обработки информации. Термины и определения — Терминология ГОСТ 25868 91: Оборудование периферийное систем обработки информации. Термины и определения оригинал документа: 77 (устройство типа) «колесо»: Колесо, вращающееся вокруг своей оси, предоставляющее значение скалярной величины.… … Словарь-справочник терминов нормативно-технической документации
Привет, Хабр! Да-да, про тестирование ПО тут уже куча статей. Здесь я просто буду стараться структурировать как можно более полный охват данных из разных источников (чтобы по теории все основное было сразу в одном месте, и новичкам, например, было легче ориентироваться). При этом, чтобы статья не казалась слишком громоздкой, информация будет представлена без излишней детализации, как необходимая и достаточная для прохождения собеседования (согласно моему опыту), рассчитанное на стажеров/джунов (как вариант, эта информация может быть для общего понимания полезна ИТ-рекрутерам, которые проводят первичное собеседование и попутно задают некоторые около-технические вопросы).
ОСНОВНЫЕ ТЕРМИНЫ
Тестирование ПО (Software Testing) — проверка соответствия между реальным и ожидаемым поведением программы, проводится на наборе тестов, который выбирается некоторым образом. Чем занимаются в тестировании:
-
планированием работ (Test Management)
-
проектированием тестов (Test Design) — этап, на котором создаются тестовые сценарии (тест кейсы), в соответствии с определёнными ранее критериями. Т.е., определяется, КАК будет тестироваться продукт.
-
выполнением тестирования (Test Execution)
-
анализом результатов (Test Analysis)
Основные цели тестирования
-
техническая: предоставление актуальной информации о состоянии продукта на данный момент.
-
коммерческая: повышение лояльности к компании и продукту, т.к. любой обнаруженный дефект негативно влияет на доверие пользователей.
Верификация (verification) |
Валидация (validation) |
Соответствие продукта требованиям (спецификации) |
Соответствие продукта потребностям пользователей |
Дефект (баг) — это несоответствие фактического результата выполнения программы ожидаемому результату.
Следует уметь различать, что:
-
Error — это ошибка пользователя, то есть он пытается использовать программу иным способом (например, вводит буквы в поля, где требуется вводить цифры). В качественной программе предусмотрены такие ситуации и выдаются сообщение об ошибке (error message).
-
Bug (defect) — это ошибка программиста (или дизайнера или ещё кого, кто принимает участие в разработке), то есть когда в программе, что-то идёт не так, как планировалось. Например, внутри программа построена так, что изначально не соответствует тому, что от неё ожидается.
-
Failure — это сбой в работе компонента, всей программы или системы (может быть как аппаратным, так и вызванным дефектом).
Жизненный цикл бага
Атрибуты дефекта
-
Серьезность (Severity) — характеризует влияние дефекта на работоспособность приложения. Выставляется тестировщиком.
Градация Серьезности дефекта
-
Blocker — ошибка, приводящая приложение в нерабочее состояние, из-за которой дальнейшая работа с системой или ее ключевыми функциями становится невозможна, т.е. тестирование значительной части функциональности становится недоступно
-
Крит (Critical) — неправильно работающая ключевая бизнес-логика, дыра в системе безопасности, проблема, приведшая к временному падению сервера или приводящая в нерабочее состояние некоторую часть системы, без возможности решения проблемы, используя другие непрямые пути (workaround).
-
Значительный (Major) — часть основной бизнес логики работает некорректно, есть возможность для работы с тестируемой функцией, используя обходные пути (workaround); либо дефект с высоким visibility – обычно не сильно влияющие на функциональность дефекты дизайна, которые, однако, сразу бросаются в глаза.
-
Minor — часто ошибки GUI, которые не влияют на функциональность, но портят юзабилити или внешний вид; либо незначительная функциональная ошибка, не нарушающая бизнес-логику тестируемой части приложения.
-
Тривиальная (Trivial) — ошибка, не касающаяся бизнес-логики приложения, не оказывающая никакого влияния на общее качество продукта, например, опечатки в тексте, несоответствие шрифта и оттенка и т.д.
-
Приоритет (Priority) — указывает на очередность выполнения задачи или устранения дефекта. Чем выше приоритет, тем быстрее нужно исправлять дефект. Выставляется менеджером, тимлидом или заказчиком.
НЕКОТОРЫЕ ТЕХНИКИ ТЕСТ-ДИЗАЙНА
-
Эквивалентное Разделение (Equivalence Partitioning) — это техника, при которой функционал (часто диапазон возможных вводимых значений) разделяется на группы эквивалентных по своему влиянию на систему значений. ПРИМЕР: есть диапазон допустимых значений от 1 до 10, выбирается одно верное значение внутри интервала (например, 5) и одно неверное значение вне интервала — 0.
-
Анализ Граничных Значений (Boundary Value Analysis) — это техника проверки поведения продукта на крайних (граничных) значениях входных данных. Если брать выше ПРИМЕР: в качестве значений для позитивного тестирования берется минимальная и максимальная границы (1 и 10), и значения больше и меньше границ (0 и 11). BVA может применяться к полям, записям, файлам, или к любого рода сущностям имеющим ограничения.
-
Доменный анализ (Domain Analysis Testing) — это техника основана на разбиении диапазона возможных значений переменной на поддиапазоны, с последующим выбором одного или нескольких значений из каждого домена для тестирования.
-
Предугадывание ошибки (Error Guessing — EG). Это когда тестировщик использует свои знания системы и способность к интерпретации спецификации на предмет того, чтобы «предугадать» при каких входных условиях система может выдать ошибку.
-
Причина / Следствие (Cause/Effect — CE). Подразумевается ввод условий, для получения ответа от системы (следствие).
-
Сценарий использования (Use Case Testing) — Use Case описывает сценарий взаимодействия двух и более участников (как правило — пользователя и системы).
-
Исчерпывающее тестирование (Exhaustive Testing — ET) — подразумевается проверка всех возможные комбинации входных значений. На практике не используется.
-
Попарное тестирование (Pairwise Testing) — это техника формирования наборов тестовых данных из полного набора входных данных в системе, которая позволяет существенно сократить общее количество тест-кейсов. Используется для тестирования, например, фильтров, сортировок. Этот интересный метод заслуживает отдельного внимания и более подробно рассматривается в статье по ссылке (в конце которой упоминаются инструменты для автоматизации применения PT).
-
Тестирование на основе состояний и переходов (State-Transition Testing) — применяется для фиксирования требований и описания дизайна приложения.
-
Таблица принятия решений (decision table) — инструмент для упорядочения бизнес-требований, которые должны быть реализованы в продукте. Применяется для систем со сложной логикой. В таблицах решений представлен набор условий, одновременное выполнение которых приводит к определенному действию.
ВИДЫ ТЕСТИРОВАНИЯ
Классификация по целям
-
Функциональное тестирование (functional testing) рассматривает заранее указанное поведение и основывается на анализе спецификации компонента или системы в целом, т.е. проверяется корректность работы функциональности приложения.
Нефункциональное тестирование (non-functional testing) — тестирование атрибутов компонента или системы, не относящихся к функциональности.
-
Тестирование пользовательского интерфейса (GUI Testing) — проверка интерфейса на соответствие требованиям (размер, шрифт, цвет, consistent behavior).
-
Тестирование удобства использования (Usability Testing) — это метод тестирования, направленный на установление степени удобства использования, обучаемости, понятности и привлекательности для пользователей разрабатываемого продукта в контексте заданных условий. Состоит из: UX — что испытывает пользователь во время использования цифрового продукта, и UI — инструмент, позволяющий осуществлять интеракцию «пользователь — веб-ресурс».
-
Тестирование безопасности (security testing) — это стратегия тестирования, используемая для проверки безопасности системы, а также для анализа рисков, связанных с обеспечением целостного подхода к защите приложения, атак хакеров, вирусов, несанкционированного доступа к конфиденциальным данным.
-
Инсталляционное тестирование (installation testing) направленно на проверку успешной установки и настройки, а также обновления или удаления приложения.
-
Конфигурационное тестирование (Configuration Testing) — специальный вид тестирования, направленный на проверку работы программного обеспечения при различных конфигурациях системы (заявленных платформах, поддерживаемых драйверах, при различных конфигурациях компьютеров и т.д.)
-
Тестирование на отказ и восстановление (Failover and Recovery Testing) проверяет тестируемый продукт с точки зрения способности противостоять и успешно восстанавливаться, т.е. обеспечивать сохранность и целостность данных, после возможных сбоев, возникших в связи с ошибками программного обеспечения, отказами оборудования или проблемами связи (например, отказ сети).
-
Тестирование локализации (localization testing) — проверка адаптации программного обеспечения для определенной аудитории в соответствии с ее культурными особенностями.
Тестирование производительности (performance testing) — определение стабильности и потребления ресурсов в условиях различных сценариев использования и нагрузок.
-
Нагрузочное тестирование (load testing) — определение или сбор показателей производительности и времени отклика программно-технической системы или устройства в ответ на внешний запрос с целью установления соответствия требованиям, предъявляемым к данной системе (устройству).
-
Тестирование стабильности или надежности (Stability / Reliability Testing) — это проверка работоспособности приложения при длительном (многочасовом) тестировании со средним уровнем нагрузки.
-
Стрессовое тестирование (Stress Testing) позволяет проверить насколько приложение и система в целом работоспособны в условиях стресса (например, повышение интенсивности выполнения операций до очень высоких значений или аварийное изменение конфигурации сервера) и также оценить способность системы к регенерации, т.е. к возвращению к нормальному состоянию после прекращения воздействия стресса.
-
Объемное тестирование (Volume Testing) — тестирование, которое проводится для получения оценки производительности при увеличении объемов данных в базе данных приложения.
-
Тестирование масштабируемости (scalability testing) — тестирование, которое измеряет производительность сети или системы, когда количество пользовательских запросов увеличивается или уменьшается.
Классификация по позитивности сценария
-
Позитивное — тест кейс использует только корректные данные и проверяет, что приложение правильно выполнило вызываемую функцию.
-
Негативное — тест кейс оперирует как корректными так и некорректными данными (минимум 1 некорректный параметр) и ставит целью проверку исключительных ситуаций; при таком тестировании часто выполняются некорректные операции.
Классификация по знанию системы
-
Тестирование белого ящика (White Box) — метод тестирования ПО, который предполагает полный доступ к коду проекта, т.е. внутренняя структура/устройство/реализация системы известны тестировщику.
-
Тестирование серого ящика — метод тестирования ПО, который предполагает частичный доступ к коду проекта (комбинация White Box и Black Box методов).
-
Тестирование чёрного ящика (Black Box) — метод тестирования ПО, также известный как тестирование, основанное на спецификации или тестирование поведения — техника тестирования, которая не предполагает доступа (полного или частичного) к системе, т.е. основывается на работе исключительно с внешним интерфейсом тестируемой системы.
Классификация по исполнителям тестирования
-
Альфа-тестирование — является ранней версией программного продукта, тестирование которой проводится внутри организации-разработчика; может быть вероятно частичное привлечение конечных пользователей.
-
Бета-тестирование — практически готовое ПО, выпускаемое для ограниченного количества пользователей, разрабатывается в первую очередь для тестирования конечными пользователями и получения отзывов клиентов о продукте для внесения соответствующих изменений.
Классификация по уровню тестирования
-
Модульное (компонентное) тестирование (Unit Testing) проводится самими разработчиками, т.к. предполагает полный доступ к коду, для тестирования какого-либо одного логически выделенного и изолированного элемента (модуля) системы в коде, проверяет функциональность и ищет дефекты в частях приложения, которые доступны и могут быть протестированы по-отдельности (модули программ, объекты, классы, функции и т.д.).
-
Интеграционное тестирование (Integration Testing) направлено на проверку корректности взаимодействия нескольких модулей, объединенных в единое целое, т.е. проверяется взаимодействие между компонентами системы после проведения компонентного тестирования.
Подходы к интеграционному тестированию
-
Снизу вверх (Bottom Up Integration) Все низкоуровневые модули, процедуры или функции собираются воедино и затем тестируются. После чего собирается следующий уровень модулей для проведения интеграционного тестирования. Данный подход считается полезным, если все или практически все модули, разрабатываемого уровня, готовы. Также данный подход помогает определить по результатам тестирования уровень готовности приложения.
-
Сверху вниз (Top Down Integration) Вначале тестируются все высокоуровневые модули, и постепенно один за другим добавляются низкоуровневые. Все модули более низкого уровня симулируются заглушками с аналогичной функциональностью, затем по мере готовности они заменяются реальными активными компонентами.
-
Большой взрыв («Big Bang» Integration) Все или практически все разработанные модули собираются вместе в виде законченной системы или ее основной части, и затем проводится интеграционное тестирование. Такой подход очень хорош для сохранения времени. Однако если тест кейсы и их результаты записаны не верно, то сам процесс интеграции сильно осложнится, что станет преградой для команды тестирования при достижении основной цели интеграционного тестирования.
-
Системное тестирование (System Testing) — это проверка как функциональных, так и не функциональных требований в системе в целом. При этом выявляются дефекты, такие как неверное использование ресурсов системы, непредусмотренные комбинации данных пользовательского уровня, несовместимость с окружением, непредусмотренные сценарии использования и т.д., и оцениваются характеристики качества системы — ее устойчивость, надежность, безопасность и производительность.
-
Операционное тестирование (Release Testing). Даже если система удовлетворяет всем требованиям, важно убедиться в том, что она удовлетворяет нуждам пользователя и выполняет свою роль в среде своей эксплуатации. Поэтому так важно провести операционное тестирование как финальный шаг валидации. Кроме этого, тестирование в среде эксплуатации позволяет выявить и нефункциональные проблемы, такие как: конфликт с другими системами, смежными в области бизнеса или в программных и электронных окружениях и др. Очевидно, что нахождение подобных вещей на стадии внедрения — критичная и дорогостоящая проблема.
Классификация по исполнению кода
-
Статическое тестирование — процесс тестирования, который проводится для верификации практически любого артефакта разработки. Например, путем анализа кода (code review). Анализ может производиться как вручную, так и с помощью специальных инструментальных средств. Целью анализа является раннее выявление ошибок и потенциальных проблем в продукте. Также к этому виду относится тестирование требований, спецификаций и прочей документации.
-
Динамическое тестирование проводится на работающей системе, т.е. с осуществлением запуска программного кода приложения.
Классификация по хронологии выполнения
-
Повторное/подтверждающее тестирование (re-testing/confirmation testing) — тестирование, во время которого исполняются тестовые сценарии, выявившие ошибки во время последнего запуска, для подтверждения успешности исправления этих ошибок, т.е. проверяется исправление багов.
-
Регрессионное тестирование (regression testing) — это тестирование после внесения изменений в код приложения (починка дефекта, слияние кода, миграция на другую операционную систему, базу данных, веб сервер или сервер приложения), для подтверждения того факта, что эти изменения не внесли ошибки в областях, которые не подверглись изменениям, т.е. проверяется то, что исправление багов, а также любые изменения в коде приложения, не повлияли на другие модули ПО и не вызвали новых багов.
-
Приёмочное тестирование проверяет соответствие системы потребностям, требованиям и бизнес-процессам пользователя.
ДОКУМЕНТАЦИЯ
Требования — это спецификация (описание) того, что должно быть реализовано. Требования описывают то, что необходимо реализовать, без детализации технической стороны решения.
Основные атрибуты требований:
-
Полнота — в требовании должна содержаться вся необходимая для реализации функциональности информация.
-
Непротиворечивость — требование не должно содержать внутренних противоречий и противоречий другим требованиям и документам.
-
Недвусмысленность — требование должно содержать однозначные формулировки.
-
Проверяемость (тестопригодность) — формулировка требований таким образом, чтобы можно было выставить однозначный вердикт, выполнено все в соответствии с требованиями или нет.
-
Приоритетность — у каждого требования должен быть приоритет (количественная оценка степени значимости требования).
Тест план (Test Plan) — документ, описывающий весь объем работ по тестированию:
-
Что нужно тестировать?
-
Как будет проводиться тестирование?
-
Когда будет проводиться тестирование?
-
Критерии начала тестирования.
-
Критерии окончания тестирования.
Основные пункты из которых может состоять тест-план перечислены в стандарте IEEE 829.
Неотъемлемой частью тест-плана является Traceability matrix — Матрица соответствия требований (МСТ) — это таблица, содержащая соответствие функциональных требований (functional requirements) продукта и подготовленных тестовых сценариев (test cases). В заголовках колонок таблицы расположены требования, а в заголовках строк — тестовые сценарии. На пересечении — отметка, означающая, что требование текущей колонки покрыто тестовым сценарием текущей строки. МСТ используется для покрытия продукта тестами.
Тестовые сценарии |
Функциональное требование 1 |
Функциональное требование 2 |
Функциональное требование 3 |
… |
test case 1 |
+ |
+ |
||
test case 2 |
+ |
+ |
||
test case 3 |
+ |
+ |
+ |
|
… |
+ |
Чек-лист (check list) — это документ, описывающий что должно быть протестировано. На сколько детальным будет чек-лист зависит от требований к отчетности, уровня знания продукта сотрудниками и сложности продукта. Чаще всего, в ЧЛ содержатся только действия, без ожидаемого результата. ЧЛ менее формализован, чем тестовый сценарий.
Тестовый сценарий (Test Case) — это документ, в котором содержатся условия, шаги и другие параметры для проверки реализации тестируемой функции или её части.
Атрибуты тест кейса:
-
Предусловия (PreConditions) используются, если предварительно систему нужно приводить к состоянию пригодному для проведения проверки; т.е. указываются либо действия, с помощью которых система оказывается в нужном состоянии, либо список условий, выполнение которых говорит о том, что система находится в нужном состоянии для основного теста.
-
Шаги (Steps) — cписок действий, переводящих систему из одного состояния в другое, для получения результата.
-
Ожидаемый результат (Expected result), на основании которого можно делать вывод о удовлетворении поставленным требованиям.
-
иногда используются Постусловия (PostConditions), как некоторое напоминание для перевода системы в первоначальное состояние, как до проведения теста (initial state)
Из тестовых сценариев, сгруппированных по некоему признаку (например, тестируемой функциональности), получаются некоторые наборы. Они могут быть как зависящими от последовательности выполнения (результат выполнения предыдущего является предварительным условием для следующего для Test script), так и независимыми (Test suite).
Отчёт о дефекте (Bug Report) — это документ, описывающий ситуацию или последовательность действий приведшую к некорректной работе функциональности.
Шапка |
Название/тема: Краткое описание (Summary) некорректного поведения, составляется по схеме WWW, т.е. ЧТО ГДЕ КОГДА (при каких условиях) |
Назначен на (Assigned To) сотрудника, который будет с ним разбираться |
|
Статус (Status) бага в соответствии с workflow |
|
Компонент приложения (Component): название тестируемой функции или ее части |
|
Информация по сборке, на которой была найдена ошибка: Номер версии (Version), название ветки |
|
Информация об окружении (Environment): ОС + версия, модель девайса (для мобильных устройств) и т.д. |
|
Серьезность (Severity) |
|
Приоритет (Priority) |
|
Описание |
Подробное описание (Description): указывается по необходимости; как правило, сюда вносятся предусловия (PreConditions) или другая дополнительная полезная информация, например, если для воспроизведения бага нужны специальные знания/данные/инструменты |
Шаги воспроизведения (Steps to Reproduce), по которым воспроизводится ситуация, приведшая к ошибке |
|
Фактический Результат (Result), полученный после прохождения шагов воспроизведения, часто может быть = теме/краткому описанию (Summary) + расшифровка чего-либо (например, ошибки по коду), если нужно |
|
Ожидаемый результат (Expected Result): который правильный, т.е. описание того, как именно должна работать система в соответствии с требованиями |
|
Прикрепленные файлы |
Вложения (Attachment): файлы с логами, скриншот или видео каст либо их комбинация для прояснения причины ошибки |
Огромное спасибо @alexlobach и @Gennadii_M за статьи! Большая часть информации взята именно оттуда.
UPD: статья пополняется. Спасибо @yakoeka
Спасибо большое всем за фидбэк, благодаря которому материал обновляется и дополняется
1. Напоминание!
Тестирование
= поиск дефектов!
Тестирование-
процесс
исследования ПО с целью
получения информации о качестве
продукта.
2. Что такое дефект (баг)?
Дефект
(он же баг) — это несоответствие
фактического результата выполнения
программы ожидаемому результату.
3. «First actual case of bug being found»
4. Как определить дефект перед нами или нет?
Программа
не делает, то что она должна
делать согласно ТЗ.
Программа
делает что-то, чего она не
должна делать согласно ТЗ.
Программа
делает что-то, о чём в
требованиях не упоминалось.
Программа
не делает чего-то, о чём не
говорится в требованиях , однако
подразумевается, что она должна это делать.
Программа
трудна для понимания и
неудобна в использовании.
5. Оформление отчёта об ошибке
Цель составления :отчета об ошибке является ее
исправление.
Каждое хорошее описание ошибки должно содержать
роено три вещи
1. Какие шаги привели к ошибке;
2. Что Вы ожидали, увидеть;
3. Что Вы на самом деле увидели.
.1 отчет в багтреккере на I баг
.1 отчет в багтреккере на один итот жебаг, который
воспроизводится браузерах/ОС.
6. Основные типы дефектов ПО
функциональные
ошибки
7. Функциональные ошибки. Примеры:
1.
Не сохраняются изменения данных в
профиле
2.
Не работает добавление комментария
3.
Не работает удаление товара из
корзины
4.
Не работает поиск
8. Основные типы дефектов ПО
функциональные ошибки
визуальные ошибки
9. Визуальные ошибки. Примеры:
1.
Текст вылезает за границы поля
2.
Элемент управления сайтом
наслаивается на нижестоящий элемент.
3.
Не отображается картинка
10. Основные типы дефектов ПО
функциональные
ошибки
визуальные ошибки
логические ошибки
11. Логические ошибки. Примеры:
1.
Можно поставить дату рождения в
будущем. 31 февраля, 31 июня и т.д.
2.
Можно сделать заказ не указав адрес
доставки
3.
Неверная работа логики поиска
12. Основные типы дефектов ПО
функциональные
ошибки
визуальные ошибки
логические ошибки
ошибки контента
13. Ошибки контента. Примеры:
1.
Конвертация валют идет по некорректному курсу.
2.
Орфографические или пунктуационные ошибки.
3.
Картинка товара не соответствует
карточке товара
14. Основные типы дефектов ПО
функциональные
ошибки
визуальные ошибки
логические ошибки
ошибки контента
ошибки удобства
использования
15. Ошибки удобства использования. Примеры:
1.
Отсутствие подсветки или текста
ошибки при некорректно заполненных
полях формы
2.
Сброс значений заполненных полей
при некорректной попытке регистрации
3.
Перегруженный интерфейс
(чрезмерное количество однотипных
точек входа)
16. Основные типы дефектов ПО
функциональные
ошибки
визуальные ошибки
логические ошибки
ошибки контента
ошибки удобства
использования
ошибки безопасности
17. Ошибки безопасности. Примеры:
1.
XSS-уязвимости
2. SQL-инъекции
18. Зачем документируют дефекты
Чтобы
Чтобы
не забыть
иметь возможность
исправлять конкретные проблемы
Чтобы собирать метрики
19. Ошибки безопасности. Примеры:
1.
XSS-уязвимости
2. SQL-инъекции
20. Простые правила оформления
Один дефект — один репорт
Говорящее название
Понятное описание
21. Оформление ошибок. Название
Локатор. Действие для проявления.
Проявление. Ожидаемый результат.
Где? Что делал? Что получилось? Что
ожидали?
22. Оформление ошибок. Описание
1. Предусловия воспроизведения
2. Последовательность действий для
воспроизведения
3. Фактический результат
4. Ожидаемый результат
23. Оформление ошибок. Доп. инфо
1. Окружение/условия воспроизведения
2. Скриншоты/видео
3. Логи/артефакты работы ПО
4. Атрибуты ошибки (важность, компонент)
24. Атрибуты бага: (Summary)
Принцип описания
сути(Summary) бага:
Что?
Где?
Когда?, (При каких условиях?)
25. Практика формулирования Summary бага.
Сформулируйте
баг на скриншоте
используя принцип: Что, где, когда?
26. Практика формулирования Summary бага.
Ответ:
Что:
Отсутствует выпадающее меню
Где:
в пункте Actionc
Когда:
при не выбранном документе.
27. Серьёзность и Приоритет багов.
СЕРЬЁЗНОСТЬ
ПРИОРИТЕТ
S1 Блокирующий (Blocker)
S2 Критический (Critical)
S3 Значительный (Major)
P1 Высокий (High)
S4 Незначительный (Minor)
P2 Средний (Medium)
S5 Тривиальный (Trivial)
P3 Низкий (Low)
28. Жизненный цикл дефекта.
29. Жизненный цикл дефекта.
30. Состояние дефектов
31. Жизненный цикл дефекта.
Варианты прохождения багов:
1. (новый)new
(отклоненный)rejected
(закрытый)closed
2. new
(отложенный)deferred
3. new
(принятый)Accepted
(открытый)open
(исправленный)fixed
(закрытый)closed
4. new
pen
accepted
(открыт снова)reopend
fixed
closed
32. Дефекты — основной продукт работы тестировщиков !!!
Improve Article
Save Article
Improve Article
Save Article
Generally, when the system/application does not act as per expectation or abnormally, we call it’s an error or it’s an fault and so on. Many of the newbies in Software Testing industry have confusion in using this, so let’s know what is the difference b/w defect, bug, error and failure. We will see these terms in detail one by one.
- Defect:
The bugs introduced by programmer inside the code is called as Defect.
Defect is defined as the deviation from the actual and expected result of application or software or in other words, defects are defined as any deviation or irregularity from the specifications mentioned in the product functional specification document. Defect is also solved by the developer in development phase or stage.
Reasons for Defects:
- Any deviation from the customer requirements is called as defect.
- By giving wrong input may lead to defect.
- Any error in logic code may lead to defect.
- Bug:
Sometimes most people are confused between defect and bug, they say that bug is the informal name of defect. Actually bugs are faults in system or application which impact on software functionality and performance. Usually bugs are found in unit testing by testers.There are different types of bugs, some of them are given below.
- Functional Errors
- Compilation Errors
- Missing commands
- Run time Errors
- Logical errors
- Inappropriate error handling
Above given these errors lead to bug.
- Failure:
When a defect reaches the end customer, it is called as Failure.
Once the product is completed and it is delivered to the customers and if the customer find any issues in product or software then it is the condition of failure of product.
In other words, if an end user finds an issue in product then that particular issue is called as failure.Causes of Failure:
- Human errors or mistakes may lead to failure.
- Environmental conditions
- The way in which system is used.
Flow of Bug to Defect:
Example:
Let’s see a defect by an example.
a=7 b=5 ans=a*b print("Addition of {} and {} = {}.".format(a, b, ans))
When you compile and run this program you see the printed statement as below:
Addition of 7 and 5=35
This is program of adding two numbers but the output is deviated from it’s actual result which is 12. Now we have detected a failure. As the failure has been detected a defect can be raised.
Improve Article
Save Article
Improve Article
Save Article
Generally, when the system/application does not act as per expectation or abnormally, we call it’s an error or it’s an fault and so on. Many of the newbies in Software Testing industry have confusion in using this, so let’s know what is the difference b/w defect, bug, error and failure. We will see these terms in detail one by one.
- Defect:
The bugs introduced by programmer inside the code is called as Defect.
Defect is defined as the deviation from the actual and expected result of application or software or in other words, defects are defined as any deviation or irregularity from the specifications mentioned in the product functional specification document. Defect is also solved by the developer in development phase or stage.
Reasons for Defects:
- Any deviation from the customer requirements is called as defect.
- By giving wrong input may lead to defect.
- Any error in logic code may lead to defect.
- Bug:
Sometimes most people are confused between defect and bug, they say that bug is the informal name of defect. Actually bugs are faults in system or application which impact on software functionality and performance. Usually bugs are found in unit testing by testers.There are different types of bugs, some of them are given below.
- Functional Errors
- Compilation Errors
- Missing commands
- Run time Errors
- Logical errors
- Inappropriate error handling
Above given these errors lead to bug.
- Failure:
When a defect reaches the end customer, it is called as Failure.
Once the product is completed and it is delivered to the customers and if the customer find any issues in product or software then it is the condition of failure of product.
In other words, if an end user finds an issue in product then that particular issue is called as failure.Causes of Failure:
- Human errors or mistakes may lead to failure.
- Environmental conditions
- The way in which system is used.
Flow of Bug to Defect:
Example:
Let’s see a defect by an example.
a=7 b=5 ans=a*b print("Addition of {} and {} = {}.".format(a, b, ans))
When you compile and run this program you see the printed statement as below:
Addition of 7 and 5=35
This is program of adding two numbers but the output is deviated from it’s actual result which is 12. Now we have detected a failure. As the failure has been detected a defect can be raised.
Индекс материала |
---|
Тестирование Дот Ком, или Пособие по жестокому обращению с багами в интернет-стартапах |
Часть I: Что такое Баг? |
Все страницы |
Страница 2 из 2
- ЧТО ТАКОЕ БАГ
- ЦЕЛЬ ТЕСТИРОВАНИЯ DECODED
- ИСКУССТВО СОЗДАНИЯ ТЕСТКЕЙСОВ
- ЦИКЛ РАЗРАБОТКИ ПО
Что такое Баг?
- Определение Бага
- Три условия жизни и процветания Бага
- Что такое тестирование
- Источники ожидаемого результата
- Функциональные баги и Баги Спека
Логический закон исключенного третьего гласит, что любая вещь — это либо А, либо не-А. Третьего не дано, т.е. если у вас есть часы «Брегет» за номером 5, то любая вещь в этом мире будет либо вашими часами «Брегет» за номером 5, либо чем-то другим.
Представим себе конвейер, в конце которого стоим мы. Лента конвейера движется, и перед нами по очереди появляется по одному предмету. Задача проста — ожидать появления ваших часов «Брегет» за номером 5 и говорить «баг» при появлении любого предмета, отличного от них.
Нетрудно догадаться, что такие предметы, как пакет кефира, будильник «Слава», буклет с предвыборными обещаниями кандидата в президенты Н. будут для нас багами.
Далее. Рассмотрим, что объединяет следующие ситуации.
- Девушка рекламирует себя как хорошую, на все руки хозяйку, а утром выясняется, что она даже яичницу пожарить не в состоянии.
- Вы купили книгу по интернет-тестированию, а в ней рассказывается о приготовлении яичницы.
- Девушка из пункта 1 прочитала книгу из пункта 2, но яичница пересолена.
Если возвыситься над яичницей, фигурирующей в каждом из трех пунктов, и абстрагироваться от женщин, карт и вина, то мы увидим, что общее — это отклонение фактического от ожидаемого.
Разбор ситуаций.
- Ожидаемый результат — девушка умеет готовить.
Фактический результат — утро без завтрака. - Ожидаемый результат — знания по тестированию.
Фактический результат — знания по кулинарии. - Ожидаемый результат — яичница будет приготовлена.
Фактический результат — еще одно утро без завтрака.
Определение бага
Итак, баг (bug) — это отклонение фактического результата (actual result) от ожидаемого результата (expected result).
В соответствии с законом исключенного третьего у нас есть баг при наличии любого фактического результата, отличного от ожидаемого.
Три условия жизни и процветания бага
Конкретный баг живет и процветает лишь при одновременном выполнении всех трех условий:
- Известен фактический результат;
- Известен ожидаемый результат;
- Известно, что результат из пункта 1 не равен результату из пункта 2.
Совет дня: каждый раз, когда возникает ситуация, в которой не совпадают фактическое и ожидаемое, — мысленно штампуйте фактическое словом «баг». Постепенно это войдет в привычку и станет рефлексом. Для ментальной тренировки не имеет значения, насколько мелочны, низки и сиюминутны ваши ожидания, главное — приобретение автоматизма.
Примеры багов из жизни:
- Бутерброд падает маслом вниз.
- Подхалимы и говоруны имеют намного больше шансов на повышение, чем скромные честные труженики.
- Несоответствие миловидной внешности и змеиной сущности.
- Попугай воспроизводит на людях худшее из словарного запаса хозяина.
- Автомобили российского производства.
- Кот Бегемот в фильме В. Бортко «Мастер и Маргарита».
Идем дальше.
Что такое тестирование
Любое тестирование — это поиск багов. Испытываем ли мы новую соковыжималку, наблюдаем ли за поведением подруги или занимаемся самокопанием — мы ищем баги. Баги находятся следующим образом:
- Мы узнаем (или уже знаем) ожидаемый результат;
- Мы узнаем (или уже знаем) фактический результат;
- Мы сравниваем пункт 1 и пункт 2.
Как видно, каждый из нас уже является тестировщиком, так как разного рода осознанные и неосознанные проверки, осуществляемые нами и в отношении нас, являются неотъемлемой частью жизни, просто раньше мы непрофессионально качали головой и выдавали тирады о несправедливости мира, но зато теперь в случае несовпадения фактического и ожидаемого мы будем с улыбкой мудреца смотреть на дилетантов, хлюпающих носами на московском ветру, и тихо, но веско (как дон Карлеоне) говорить: «Та-а-к, еще один баг».
Для иллюстрации правильного подхода приведу в пример одного моего друга, который выстроил целую систему доказательств тезиса, что люди и компьютеры созданы по одному образцу. Основой его аргументации явился тот факт, что и те и другие имеют физическую оболочку (тело/железо) и неосязаемое составляющее, управляющее ею (душа/ПО). Соответственно болезни тела он называл багами в железе, а проблемы с головой — багами в ПО и очень сожалел, что ПО людей, управляющих этим миром, состоит в основном из багов…
Теперь вспомним о том, что есть компьютерное ПО и что нам нужно научиться его тестировать.
С фактическим результатом здесь более или менее понятно: нужно заставить систему проявить себя и посмотреть, что произойдет.
Сложнее дело обстоит с ожидаемым результатом.
Источники ожидаемого результата
Основными источниками ожидаемого результата являются:
- Спецификация.
- Спецификация.
- Спецификация.
- Спецификация.
- Жизненный опыт, здравый смысл, общение, устоявшиеся стандарты, статистические данные, авторитетное мнение и др.
Спецификация на первой— четвертой ролях — это не ошибка, а ударение на то, что спецификация для тестировщика — это:
- мать родная, а также
- друг,
- товарищ и
- брат.
Спецификация важна для программиста и тестировщика так же, как постановление пленума ЦК для коммуниста.
Спецификация — это инструмент, с помощью которого вы сможете выпустить качественный продукт и прикрыть свою спину (в оригинале звучит как CYA или cover your ass).
Итак, что же это за зверь?
Спецификация (или spec — читается «спек». Далее употребляется в мужском роде) — это детальное описание того, как должно работать ПО. Вот так, ни много ни мало.
В большинстве случаев баг — это отклонение от спецификации (я говорю о компаниях, в которых спеки в принципе существуют и ими пользуются).
Пример
Пункт 19.а спека #8724 «О регистрации нового пользователя» устанавливает: «Поле «Имя» должно быть обязательным. Страница с ошибкой должна быть показана, если пользователь посылает регистрационную форму без заполнения указанного поля».
В общем все просто:
- тестировщик идет на страничку с регистрационной формой;
- кликает линк «Регистрация»;
- заполняет все обязательные поля, кроме поля «Имя»;
- нажимает на кнопку «Зарегистрироваться».
Если ошибка не показана и регистрация подтверждается, то это есть момент истины и нужно рапортовать баг (file a bug).
Если ошибка показана, то относительно пункта 19.а на некоторое время можно успокоиться. Мы поймем, почему можно успокоиться лишь на некоторое время при разговоре о регрессионном тестировании…
Функциональные баги и баги спека
Допустим, что ошибка не была показана и мы имеем классический случай функционального бага (functional bug, или баг обыкновенный), т.е. бага, вскормленного на несоответствии фактической работы кода и функционального спека.
Если вы внимательно читали пункт 19.а, то не могли не заметить (шутка), что непонятно, какое должно быть сообщение об ошибке (error message), т.е. фактически решение отдано на откуп про-граммисту и он может предусмотреть, что при соответствующей ситуации код выдаст:
- Не информативное сообщение «Ошибка» и оставит пользователя ломать голову над тем, что он сделал неправильно, либо
- информативное сообщение «Пожалуйста, введите ваше имя и нажмите кнопку «Регистрация»»
и в любом случае формально будет прав, так как спецификация не детализирует текста ошибки.
Кстати, несколько лет назад был случай, когда программисты в специальном ПО, разработанном для американских тюрем, оставили «рабочее» название кнопки, причем тюремщикам идея так понравилась, что они просили ничего не исправлять. Надпись на кнопке была: «Освободить подонка».
В общем сложилась ситуация, когда сама спецификация имеет проблему, так как мы ожидаем (или по крайней мере должны ожидать), что в спеке будут подробности о тексте ошибки, а в реальности их там нет. Так и запишем — «баг в спецификации» (spec bug).
Кстати, вот варианты развития ситуации с проблемным спеком:
- Скорее всего программист все же напишет нформативное сообщение об ошибке. Ваше дело послать емейл продюсеру (продюсером в интернет компании называют товарища, создающего спеки), чтобы тот внес текст, уже написанный программистом, в пункт 19.а.
- Если программист написал нечто противоречащее здравому смыслу или стандарту, принятому в вашей компании, рапортуйте баг.
- Может случиться так, что вы не заметили проблемы в спеке и не заметили, как программист написал сообщение об ошибке, противоречащее здравому смыслу или стандарту, принятому в вашей компании.
Кстати, вот две релевантные политически важные вещи:
- Как правило, работа в стартапе — это уникальный опыт, когда тяжелый труд сочетается с радостью созидания, расслабленной обстановкой (я, например, уже многие годы хожу на работу в шортах) и окружающими вас милыми, веселыми людьми. Но бывают нештатные ситуации (например, работа не сделана в срок или сделана не качественно), и, когда дело дойдет до выяснения «кто виноват» и «что с ним сделать», многие из ваших коллег перестанут быть милыми, веселыми людьми и активно начнут вешать собак друг на друга. Так вот, чтобы одну из этих собак не повесили на вас, посылайте емейлы, сохраняйте их и ответы на них и при случае пересылайте их заинтересованным сторонам. Пригодятся те емейлы в дальнейшем — хорошо, не пригодятся — еще лучше, тем более что каши они не просят, а сидят себе тихо и малодушно в своих фолдерах и ничего не ждут от этой жизни.
- Каждый должен заниматься своим делом и отвечать за свой участок работы. В случае если спек сделан некачественно, то лучше поднять тревогу с рассылкой емейлов, чем делать допущения относительно того, как должно работать ваше ПО.
Перед завершением темы об ожидаемом и фактическом результатах рассмотрим примеры других источников ожидаемого результата, кроме спеков.
ЖИЗНЕННЫЙ ОПЫТ
Как справедливо отметил Борис Слуцкий: «Не только пиво-раки мы ели и лакали». Мы также учились и работали, любили и ненавидели, верили политикам и не слушались родителей, в общем приобретали жизненный опыт (включая опыт работы). Так вот этот опыт настолько полезен в нашем черном деле, что для демонстрации уважения к идее о его полезности (вместе с логикой и здравым смыслом) я вынес ее в качестве эпиграфа во Введении. Дело в том, что тестирование ПО — это то самое тестирование (которое мы делаем постоянно), но только в отношении ПО. И моя задача заключается лишь в том, чтобы дать вам основные концепции и практический инструментарий по интернет-тестированию и помочь их интеграции с тем, что у вас уже есть, — с жизненным опытом.
ЗДРАВЫЙ СМЫСЛ (дитя жизненного опыта и соответственно внук «ошибок трудных»)
Это один из наших главных союзников, порой даже и при наличии спека. Например, вы тестируете веб-сайт, где пользователь может загрузить (upload) свои цифровые фотографии. Спек говорит, что пользователь может загрузить лишь одну фотографию за раз. А что, если у него таких фотографий 200? Будет он счастлив? Что делаем? Правильно: пишем е-мейл к
Этот e-mail адрес защищен от спам-ботов, для его просмотра у Вас должен быть включен Javascript
с предложением о включении в спек функциональности, позволяющей пользователю загружать цифровые фотографии оптом. Кстати, баг такого рационализаторского плана лицемерно называется не багом, а Feature Request («запрос об улучшении» — пока остановимся на таком переводе).
ОБЩЕНИЕ
Даже самый лучший спек может вызвать необходимость в уточнениях. А что, если спека нет вообще? Наш ответ: общение. Советуйтесь с коллегами. Уточняйте и обсуждайте. Одна голова хорошо, а две лучше.
УСТОЯВШИЕСЯ СТАНДАРТЫ
Как правило, после регистрации, пользователь должен получить е-мейл с подтверждением. Если спек не упоминает о таком е-мейле, вы можете потребовать дополнить его на основании сложившейся практики.
СТАТИСТИЧЕСКИЕ ДАННЫЕ
Было установлено, что средний пользователь теряет терпение, если web page (веб-страница) не загружается в течение 5 секунд. Эти данные можно использовать, проводя performance testing (тестирование скорости работы всей системы либо ее компонента). Как говорят американцы: «Your user is just one click away from your competitor» («Ваш пользователь находится на расстоянии в один клик от вашего конкурента»). Успех вашего проекта — это счастливые пользователи. Превышение 5 секунд — это превращение веб-сайта в зал ожиданий, в котором вряд ли кто захочет находиться.
АВТОРИТЕТНОЕ МНЕНИЕ
Это может быть, например, мнение вашего начальника.
ДР.
Другие.
Отметим, что баг (bug) буквально переводится как «жук» или «букашка».
Теперь, как я и обещал, немного истории.
Согласно фольклору, баги вошли в лексикон компьютерщиков после случая, происшедшего в Гарвардском университете в 1947 г. После того как на реле прадедушки ПК Маркa II присел отдохнуть мотылек, один из контактов слегка коротнуло и весь 15тонный агрегат со скрежетом остановился. Инженеры проявили милосердие и извлекли мотылька, после чего аккуратно зафиксировали его скотчем в журнале испытаний с комментарием «Первый фактический случай найденного жука» («First actual case of bug being found»).
Итак,
Краткое подведение итогов
- Баг — это отклонение фактического результата от ожидаемого.
- Главный источник ожидаемого результата в интернет-компании — это спецификация.
- Спецификации сами не без греха, и в этом случае, как и в случае полного их отсутствия, у нас есть здравый смысл, устоявшиеся стандарты, опыт работы, статистика, авторитетное мнение и др.
Задания для самопроверки
- Ищите баги в чем угодно, введите это слово в свой лексикон и расписывайте самые яркие из них на листе бумаги по схеме: Ожидаемый результат/Фактический результат.
- Подумайте, какие еще источники ожидаемого результата могут быть в работе тестировщика.
- Побродите по Интернету, порегистрируйтесь (www.yahoo.com, www.hotmail.com и т.д.) и составьте список обязательных полей (required fields) на регистрационных формах.
Обработка исключительных ситуаций. Методы и способы идентификации сбоев и ошибок.
Конструкция try..catch..finally
Иногда при выполнении программы возникают ошибки, которые трудно предусмотреть или предвидеть, а иногда и вовсе невозможно. Например, при передачи файла по сети может неожиданно оборваться сетевое подключение. такие ситуации называются исключениями. Язык C# предоставляет разработчикам возможности для обработки таких ситуаций. Для этого в C# предназначена конструкция try…catch…finally.
try { } catch { } finally { }
При использовании блока try…catch..finally вначале пытаются выполниться инструкции в блоке try. Если в этом блоке не возникло исключений, то после его выполнения начинает выполняться блок finally. И затем конструкция try..catch..finally завершает свою работу.
Если же в блоке try вдруг возникает исключение, то обычный порядок выполнения останавливается, и среда CLR (Common Language Runtime) начинает искать блок catch, который может обработать данное исключение. Если нужный блок catch найден, то он выполняется, и после его завершения выполняется блок finally.
Если нужный блок catch не найден, то при возникновении исключения программа аварийно завершает свое выполнение.
Рассмотрим следующий пример:
class Program { static void Main(string[] args) { int x = 5; int y = x / 0; Console.WriteLine($"Результат: {y}"); Console.WriteLine("Конец программы"); Console.Read(); } }
В данном случае происходит деление числа на 0, что приведет к генерации исключения. И при запуске приложения в режиме отладки мы увидим в Visual Studio окошко, которое информирует об исключении:
В этом окошке мы видим, что возникло исключение, которое представляет тип System.DivideByZeroException, то есть попытка деления на ноль. С помощью пункта View Details можно посмотреть более детальную информацию об исключении.
И в этом случае единственное, что нам остается, это завершить выполнение программы.
Чтобы избежать подобного аварийного завершения программы, следует использовать для обработки исключений конструкцию try…catch…finally. Так, перепишем пример следующим образом:
class Program { static void Main(string[] args) { try { int x = 5; int y = x / 0; Console.WriteLine($"Результат: {y}"); } catch { Console.WriteLine("Возникло исключение!"); } finally { Console.WriteLine("Блок finally"); } Console.WriteLine("Конец программы"); Console.Read(); } }
В данном случае у нас опять же возникнет исключение в блоке try, так как мы пытаемся разделить на ноль. И дойдя до строки
выполнение программы остановится. CLR найдет блок catch и передаст управление этому блоку.
После блока catch будет выполняться блок finally.
Возникло исключение!
Блок finally
Конец программы
Таким образом, программа по-прежнему не будет выполнять деление на ноль и соответственно не будет выводить результат этого деления, но теперь она не будет аварийно завершаться, а исключение будет обрабатываться в блоке catch.
Следует отметить, что в этой конструкции обязателен блок try. При наличии блока catch мы можем опустить блок finally:
try { int x = 5; int y = x / 0; Console.WriteLine($"Результат: {y}"); } catch { Console.WriteLine("Возникло исключение!"); }
И, наоборот, при наличии блока finally мы можем опустить блок catch и не обрабатывать исключение:
try { int x = 5; int y = x / 0; Console.WriteLine($"Результат: {y}"); } finally { Console.WriteLine("Блок finally"); }
Однако, хотя с точки зрения синтаксиса C# такая конструкция вполне корректна, тем не менее, поскольку CLR не сможет найти нужный блок catch, то исключение не будет обработано, и программа аварийно завершится.
Обработка исключений и условные конструкции
Ряд исключительных ситуаций может быть предвиден разработчиком. Например, пусть программа предусматривает ввод числа и вывод его квадрата:
static void Main(string[] args) { Console.WriteLine("Введите число"); int x = Int32.Parse(Console.ReadLine()); x *= x; Console.WriteLine("Квадрат числа: " + x); Console.Read(); }
Если пользователь введет не число, а строку, какие-то другие символы, то программа выпадет в ошибку. С одной стороны, здесь как раз та ситуация, когда можно применить блок try..catch, чтобы обработать возможную ошибку. Однако гораздо оптимальнее было бы проверить допустимость преобразования:
static void Main(string[] args) { Console.WriteLine("Введите число"); int x; string input = Console.ReadLine(); if (Int32.TryParse(input, out x)) { x *= x; Console.WriteLine("Квадрат числа: " + x); } else { Console.WriteLine("Некорректный ввод"); } Console.Read(); }
Метод Int32.TryParse() возвращает true, если преобразование можно осуществить, и false — если нельзя. При допустимости преобразования переменная x будет содержать введенное число. Так, не используя try…catch можно обработать возможную исключительную ситуацию.
С точки зрения производительности использование блоков try..catch более накладно, чем применение условных конструкций. Поэтому по возможности вместо try..catch лучше использовать условные конструкции на проверку исключительных ситуаций.
Блок catch и фильтры исключений
Определение блока catch
За обработку исключения отвечает блок catch, который может иметь следующие формы:
-
Обрабатывает любое исключение, которое возникло в блоке try. Выше уже был продемонстрирован пример подобного блока.
catch { // выполняемые инструкции }
-
Обрабатывает только те исключения, которые соответствуют типу, указаному в скобках после оператора catch.
catch (тип_исключения) { // выполняемые инструкции }
Например, обработаем только исключения типа DivideByZeroException:
try { int x = 5; int y = x / 0; Console.WriteLine($"Результат: {y}"); } catch(DivideByZeroException) { Console.WriteLine("Возникло исключение DivideByZeroException"); }
Однако если в блоке try возникнут исключения каких-то других типов, отличных от DivideByZeroException, то они не будут обработаны.
-
Обрабатывает только те исключения, которые соответствуют типу, указаному в скобках после оператора catch. А вся информация об исключении помещается в переменную данного типа.
catch (тип_исключения имя_переменной) { // выполняемые инструкции }
Например:
try { int x = 5; int y = x / 0; Console.WriteLine($"Результат: {y}"); } catch(DivideByZeroException ex) { Console.WriteLine($"Возникло исключение {ex.Message}"); }
Фактически этот случай аналогичен предыдущему за тем исключением, что здесь используется переменная. В данном случае в переменную ex, которая представляет тип DivideByZeroException, помещается информация о возникшем исключени. И с помощью свойства Message мы можем получить сообщение об ошибке.
Если нам не нужна информация об исключении, то переменную можно не использовать как в предыдущем случае.
Фильтры исключений
Фильтры исключений позволяют обрабатывать исключения в зависимости от определенных условий. Для их применения после выражения catch идет выражение when, после которого в скобках указывается условие:
В этом случае обработка исключения в блоке catch производится только в том случае, если условие в выражении when истинно. Например:
int x = 1; int y = 0; try { int result = x / y; } catch(DivideByZeroException) when (y==0 && x == 0) { Console.WriteLine("y не должен быть равен 0"); } catch(DivideByZeroException ex) { Console.WriteLine(ex.Message); }
В данном случае будет выброшено исключение, так как y=0. Здесь два блока catch, и оба они обрабатывают исключения типа DivideByZeroException, то есть по сути все исключения, генерируемые при делении на ноль. Но поскольку для первого блока указано условие y == 0 && x == 0, то оно не будет обрабатывать исключение — условие, указанное после оператора when возвращает false. Поэтому CLR будет дальше искать соответствующие блоки catch далее и для обработки исключения выберет второй блок catch. В итоге если мы уберем второй блок catch, то исключение вобще не будет обрабатываться.
Типы исключений. Класс Exception
Базовым для всех типов исключений является тип Exception. Этот тип определяет ряд свойств, с помощью которых можно получить информацию об исключении.
-
InnerException: хранит информацию об исключении, которое послужило причиной текущего исключения
-
Message: хранит сообщение об исключении, текст ошибки
-
Source: хранит имя объекта или сборки, которое вызвало исключение
-
StackTrace: возвращает строковое представление стека вызывов, которые привели к возникновению исключения
-
TargetSite: возвращает метод, в котором и было вызвано исключение
Например, обработаем исключения типа Exception:
static void Main(string[] args) { try { int x = 5; int y = x / 0; Console.WriteLine($"Результат: {y}"); } catch (Exception ex) { Console.WriteLine($"Исключение: {ex.Message}"); Console.WriteLine($"Метод: {ex.TargetSite}"); Console.WriteLine($"Трассировка стека: {ex.StackTrace}"); } Console.Read(); }
Однако так как тип Exception является базовым типом для всех исключений, то выражение catch (Exception ex) будет обрабатывать все исключения, которые могут возникнуть.
Но также есть более специализированные типы исключений, которые предназначены для обработки каких-то определенных видов исключений. Их довольно много, я приведу лишь некоторые:
-
DivideByZeroException: представляет исключение, которое генерируется при делении на ноль
-
ArgumentOutOfRangeException: генерируется, если значение аргумента находится вне диапазона допустимых значений
-
ArgumentException: генерируется, если в метод для параметра передается некорректное значение
-
IndexOutOfRangeException: генерируется, если индекс элемента массива или коллекции находится вне диапазона допустимых значений
-
InvalidCastException: генерируется при попытке произвести недопустимые преобразования типов
-
NullReferenceException: генерируется при попытке обращения к объекту, который равен null (то есть по сути неопределен)
И при необходимости мы можем разграничить обработку различных типов исключений, включив дополнительные блоки catch:
static void Main(string[] args) { try { int[] numbers = new int[4]; numbers[7] = 9; // IndexOutOfRangeException int x = 5; int y = x / 0; // DivideByZeroException Console.WriteLine($"Результат: {y}"); } catch (DivideByZeroException) { Console.WriteLine("Возникло исключение DivideByZeroException"); } catch (IndexOutOfRangeException ex) { Console.WriteLine(ex.Message); } Console.Read(); }
В данном случае блоки catch обрабатывают исключения типов IndexOutOfRangeException, DivideByZeroException и Exception. Когда в блоке try возникнет исключение, то CLR будет искать нужный блок catch для обработки исключения. Так, в данном случае на строке
происходит обращение к 7-му элементу массива. Однако поскольку в массиве только 4 элемента, то мы получим исключение типа IndexOutOfRangeException. CLR найдет блок catch, который обрабатывает данное исключение, и передаст ему управление.
Следует отметить, что в данном случае в блоке try есть ситуация для генерации второго исключения — деление на ноль. Однако поскольку после генерации IndexOutOfRangeException управление переходит в соответствующий блок catch, то деление на ноль int y = x / 0
в принципе не будет выполняться, поэтому исключение типа DivideByZeroException никогда не будет сгенерировано.
Однако рассмотрим другую ситуацию:
static void Main(string[] args) { try { object obj = "you"; int num = (int)obj; // InvalidCastException Console.WriteLine($"Результат: {num}"); } catch (DivideByZeroException) { Console.WriteLine("Возникло исключение DivideByZeroException"); } catch (IndexOutOfRangeException) { Console.WriteLine("Возникло исключение IndexOutOfRangeException"); } Console.Read(); }
В данном случае в блоке try генерируется исключение типа InvalidCastException, однако соответствующего блока catch для обработки данного исключения нет. Поэтому программа аварийно завершит свое выполнение.
Мы также можем определить для InvalidCastException свой блок catch, однако суть в том, что теоретически в коде могут быть сгенерированы сами различные типы исключений. А определять для всех типов исключений блоки catch, если обработка исключений однотипна, не имеет смысла. И в этом случае мы можем определить блок catch для базового типа Exception:
static void Main(string[] args) { try { object obj = "you"; int num = (int)obj; // InvalidCastException Console.WriteLine($"Результат: {num}"); } catch (DivideByZeroException) { Console.WriteLine("Возникло исключение DivideByZeroException"); } catch (IndexOutOfRangeException) { Console.WriteLine("Возникло исключение IndexOutOfRangeException"); } catch (Exception ex) { Console.WriteLine($"Исключение: {ex.Message}"); } Console.Read(); }
И в данном случае блок catch (Exception ex){}
будет обрабатывать все исключения кроме DivideByZeroException и IndexOutOfRangeException. При этом блоки catch для более общих, более базовых исключений следует помещать в конце — после блоков catch для более конкретный, специализированных типов. Так как CLR выбирает для обработки исключения первый блок catch, который соответствует типу сгенерированного исключения. Поэтому в данном случае сначала обрабатывается исключение DivideByZeroException и IndexOutOfRangeException, и только потом Exception (так как DivideByZeroException и IndexOutOfRangeException наследуется от класса Exception).
Создание классов исключений
Если нас не устраивают встроенные типы исключений, то мы можем создать свои типы. Базовым классом для всех исключений является класс Exception, соответственно для создания своих типов мы можем унаследовать данный класс.
Допустим, у нас в программе будет ограничение по возрасту:
class Program { static void Main(string[] args) { try { Person p = new Person { Name = "Tom", Age = 17 }; } catch (Exception ex) { Console.WriteLine($"Ошибка: {ex.Message}"); } Console.Read(); } } class Person { private int age; public string Name { get; set; } public int Age { get { return age; } set { if (value < 18) { throw new Exception("Лицам до 18 регистрация запрещена"); } else { age = value; } } } }
В классе Person при установке возраста происходит проверка, и если возраст меньше 18, то выбрасывается исключение. Класс Exception принимает в конструкторе в качестве параметра строку, которое затем передается в его свойство Message.
Но иногда удобнее использовать свои классы исключений. Например, в какой-то ситуации мы хотим обработать определенным образом только те исключения, которые относятся к классу Person. Для этих целей мы можем сделать специальный класс PersonException:
class PersonException : Exception { public PersonException(string message) : base(message) { } }
По сути класс кроме пустого конструктора ничего не имеет, и то в конструкторе мы просто обращаемся к конструктору базового класса Exception, передавая в него строку message. Но теперь мы можем изменить класс Person, чтобы он выбрасывал исключение именно этого типа и соответственно в основной программе обрабатывать это исключение:
class Program { static void Main(string[] args) { try { Person p = new Person { Name = "Tom", Age = 17 }; } catch (PersonException ex) { Console.WriteLine("Ошибка: " + ex.Message); } Console.Read(); } } class Person { private int age; public int Age { get { return age; } set { if (value < 18) throw new PersonException("Лицам до 18 регистрация запрещена"); else age = value; } } }
Однако необязательно наследовать свой класс исключений именно от типа Exception, можно взять какой-нибудь другой производный тип. Например, в данном случае мы можем взять тип ArgumentException, который представляет исключение, генерируемое в результате передачи аргументу метода некорректного значения:
class PersonException : ArgumentException { public PersonException(string message) : base(message) { } }
Каждый тип исключений может определять какие-то свои свойства. Например, в данном случае мы можем определить в классе свойство для хранения устанавливаемого значения:
class PersonException : ArgumentException { public int Value { get;} public PersonException(string message, int val) : base(message) { Value = val; } }
В конструкторе класса мы устанавливаем это свойство и при обработке исключения мы его можем получить:
class Person { public string Name { get; set; } private int age; public int Age { get { return age; } set { if (value < 18) throw new PersonException("Лицам до 18 регистрация запрещена", value); else age = value; } } } class Program { static void Main(string[] args) { try { Person p = new Person { Name = "Tom", Age = 13 }; } catch (PersonException ex) { Console.WriteLine($"Ошибка: {ex.Message}"); Console.WriteLine($"Некорректное значение: {ex.Value}"); } Console.Read(); } }
Поиск блока catch при обработке исключений
Если код, который вызывает исключение, не размещен в блоке try или помещен в конструкцию try..catch, которая не содержит соответствующего блока catch для обработки возникшего исключения, то система производит поиск соответствующего обработчика исключения в стеке вызовов.
Например, рассмотрим следующую программу:
using System; namespace HelloApp { class Program { static void Main(string[] args) { try { TestClass.Method1(); } catch (DivideByZeroException ex) { Console.WriteLine($"Catch в Main : {ex.Message}"); } finally { Console.WriteLine("Блок finally в Main"); } Console.WriteLine("Конец метода Main"); Console.Read(); } } class TestClass { public static void Method1() { try { Method2(); } catch (IndexOutOfRangeException ex) { Console.WriteLine($"Catch в Method1 : {ex.Message}"); } finally { Console.WriteLine("Блок finally в Method1"); } Console.WriteLine("Конец метода Method1"); } static void Method2() { try { int x = 8; int y = x / 0; } finally { Console.WriteLine("Блок finally в Method2"); } Console.WriteLine("Конец метода Method2"); } } }
В данном случае стек вызовов выглядит следующим образом: метод Main вызывает метод Method1, который, в свою очередь, вызывает метод Method2. И в методе Method2 генерируется исключение DivideByZeroException. Визуально стек вызовов можно представить следующим образом:
Внизу стека метод Main, с которого началось выполнение, и на самом верху метод Method2.
Что будет происходить в данном случае при генерации исключения?
-
Метод Main вызывает метод Method1, а тот вызывает метод Method2, в котором генерируется исключение DivideByZeroException.
-
Система видит, что код, который вызывал исключение, помещен в конструкцию try..catch
try { int x = 8; int y = x / 0; } finally { Console.WriteLine("Блок finally в Method2"); }
Система ищет в этой конструкции блок catch, который обрабатывает исключение DivideByZeroException. Однако такого блока catch нет.
-
Система опускается в стеке вызовов в метод Method1, который вызывал Method2. Здесь вызов Method2 помещен в конструкцию try..catch
try { Method2(); } catch (IndexOutOfRangeException ex) { Console.WriteLine($"Catch в Method1 : {ex.Message}"); } finally { Console.WriteLine("Блок finally в Method1"); }
Система также ищет в этой конструкции блок catch, который обрабатывает исключение DivideByZeroException. Однако здесь также подобный блок catch отсутствует.
-
Система далее опускается в стеке вызовов в метод Main, который вызывал Method1. Здесь вызов Method1 помещен в конструкцию try..catch
try { TestClass.Method1(); } catch (DivideByZeroException ex) { Console.WriteLine($"Catch в Main : {ex.Message}"); } finally { Console.WriteLine("Блок finally в Main"); }
Система снова ищет в этой конструкции блок catch, который обрабатывает исключение DivideByZeroException. И в данном случае ткой блок найден.
-
Система наконец нашла нужный блок catch в методе Main, для обработки исключения, которое возникло в методе Method2 — то есть к начальному методу, где непосредственно возникло исключение. Но пока данный блок catch НЕ выполняется. Система поднимается обратно по стеку вызовов в самый верх в метод Method2 и выполняет в нем блок finally:
finally { Console.WriteLine("Блок finally в Method2"); }
-
Далее система возвращается по стеку вызовов вниз в метод Method1 и выполняет в нем блок finally:
finally { Console.WriteLine("Блок finally в Method1"); }
-
Затем система переходит по стеку вызовов вниз в метод Main и выполняет в нем найденный блок catch и последующий блок finally:
catch (DivideByZeroException ex) { Console.WriteLine($"Catch в Main : {ex.Message}"); } finally { Console.WriteLine("Блок finally в Main"); }
-
Далее выполняется код, который идет в методе Main после конструкции try..catch:
Console.WriteLine("Конец метода Main");
Стоит отметить, что код, который идет после конструкции try…catch в методах Method1 и Method2, не выполняется, потому что обработчик исключения найден именно в методе Main.
Консольный вывод программы:
Блок finally в Method2
Блок finally в Method1
Catch в Main: Попытка деления на нуль.
Блок finally в Main
Конец метода Main
Генерация исключения и оператор throw
Обычно система сама генерирует исключения при определенных ситуациях, например, при делении числа на ноль. Но язык C# также позволяет генерировать исключения вручную с помощью оператора throw. То есть с помощью этого оператора мы сами можем создать исключение и вызвать его в процессе выполнения.
Например, в нашей программе происходит ввод строки, и мы хотим, чтобы, если длина строки будет больше 6 символов, возникало исключение:
static void Main(string[] args) { try { Console.Write("Введите строку: "); string message = Console.ReadLine(); if (message.Length > 6) { throw new Exception("Длина строки больше 6 символов"); } } catch (Exception e) { Console.WriteLine($"Ошибка: {e.Message}"); } Console.Read(); }
После оператора throw указывается объект исключения, через конструктор которого мы можем передать сообщение об ошибке. Естественно вместо типа Exception мы можем использовать объект любого другого типа исключений.
Затем в блоке catch сгенерированное нами исключение будет обработано.
Подобным образом мы можем генерировать исключения в любом месте программы. Но существует также и другая форма использования оператора throw, когда после данного оператора не указывается объект исключения. В подобном виде оператор throw может использоваться только в блоке catch:
try { try { Console.Write("Введите строку: "); string message = Console.ReadLine(); if (message.Length > 6) { throw new Exception("Длина строки больше 6 символов"); } } catch { Console.WriteLine("Возникло исключение"); throw; } } catch (Exception ex) { Console.WriteLine(ex.Message); }
В данном случае при вводе строки с длиной больше 6 символов возникнет исключение, которое будет обработано внутренним блоком catch. Однако поскольку в этом блоке используется оператор throw, то исключение будет передано дальше внешнему блоку catch.
Методы поиска ошибок в программах
Международный стандарт ANSI/IEEE-729-83 разделяет все ошибки в разработке программ на следующие типы.
Ошибка (error) — состояние программы, при котором выдаются неправильные результаты, причиной которых являются изъяны (flaw) в операторах программы или в технологическом процессе ее разработки, что приводит к неправильной интерпретации исходной информации, следовательно, и к неверному решению.
Дефект (fault) в программе — следствие ошибок разработчика на любом из этапов разработки, которая может содержаться в исходных или проектных спецификациях, текстах кодов программ, эксплуатационной документация и т.п. В процессе выполнения программы может быть обнаружен дефект или сбой.
Отказ (failure) — это отклонение программы от функционирования или невозможность программы выполнять функции, определенные требованиями и ограничениями, что рассматривается как событие, способствующее переходу программы в неработоспособное состояние из-за ошибок, скрытых в ней дефектов или сбоев в среде функционирования [7.6, 7.11]. Отказ может быть результатом следующих причин:
- ошибочная спецификация или пропущенное требование, означающее, что спецификация точно не отражает того, что предполагал пользователь;
- спецификация может содержать требование, которое невозможно выполнить на данной аппаратуре и программном обеспечении;
- проект программы может содержать ошибки (например, база данных спроектирована без средств защиты от несанкционированного доступа пользователя, а требуется защита);
- программа может быть неправильной, т.е. она выполняет несвойственный алгоритм или он реализован не полностью.
Таким образом, отказы, как правило, являются результатами одной или более ошибок в программе, а также наличия разного рода дефектов.
Ошибки на этапах процесса тестирования. Приведенные типы ошибок распределяются по этапам ЖЦ и им соответствуют такие источники их возникновения:
- непреднамеренное отклонение разработчиков от рабочих стандартов или планов реализации;
- спецификации функциональных и интерфейсных требований выполнены без соблюдения стандартов разработки, что приводит к нарушению функционирования программ;
- организации процесса разработки — несовершенная или недостаточное управление руководителем проекта ресурсами (человеческими, техническими, программными и т.д.) и вопросами тестирования и интеграции элементов проекта.
Рассмотрим процесс тестирования, исходя из рекомендаций стандарта ISO/IEC 12207, и приведем типы ошибок, которые обнаруживаются на каждом процессе ЖЦ.
Процесс разработки требований. При определении исходной концепции системы и исходных требований к системе возникают ошибки аналитиков при спецификации верхнего уровня системы и построении концептуальной модели предметной области.
Характерными ошибками этого процесса являются:
- неадекватность спецификации требований конечным пользователям;
- некорректность спецификации взаимодействия ПО со средой функционирования или с пользователями;
- несоответствие требований заказчика к отдельным и общим свойствам ПО;
- некорректность описания функциональных характеристик;
- необеспеченность инструментальными средствами всех аспектов реализации требований заказчика и др.
Процесс проектирования. Ошибки при проектировании компонентов могут возникать при описании алгоритмов, логики управления, структур данных, интерфейсов, логики моделирования потоков данных, форматов ввода-вывода и др. В основе этих ошибок лежат дефекты спецификаций аналитиков и недоработки проектировщиков. К ним относятся ошибки, связанные:
- с определением интерфейса пользователя со средой;
- с описанием функций (неадекватность целей и задач компонентов, которые обнаруживаются при проверке комплекса компонентов);
- с определением процесса обработки информации и взаимодействия между процессами (результат некорректного определения взаимосвязей компонентов и процессов);
- с некорректным заданием данных и их структур при описании отдельных компонентов и ПС в целом;
- с некорректным описанием алгоритмов модулей;
- с определением условий возникновения возможных ошибок в программе;
- с нарушением принятых для проекта стандартов и технологий.
Этап кодирования. На данном этапе возникают ошибки, которые являются результатом дефектов проектирования, ошибок программистов и менеджеров в процессе разработки и отладки системы. Причиной ошибок являются:
- бесконтрольность значений входных параметров, индексов массивов, параметров циклов, выходных результатов, деления на 0 и др.;
- неправильная обработка нерегулярных ситуаций при анализе кодов возврата от вызываемых подпрограмм, функций и др.;
- нарушение стандартов кодирования (плохие комментарии, нерациональное выделение модулей и компонент и др.);
- использование одного имени для обозначения разных объектов или разных имен одного объекта, плохая мнемоника имен;
- несогласованное внесение изменений в программу разными разработчиками и др.
Процесс тестирования. На этом процессе ошибки допускаются программистами и тестировщиками при выполнении технологии сборки и тестирования, выбора тестовых наборов и сценариев тестирования и др. Отказы в программном обеспечении, вызванные такого рода ошибками, должны выявляться, устраняться и не отражаться на статистике ошибок компонент и программного обеспечения в целом.
Процесс сопровождения. На процессе сопровождения обнаруживаются ошибки, причиной которых являются недоработки и дефекты эксплуатационной документации, недостаточные показатели модифицируемости и удобочитаемости, а также некомпетентность лиц, ответственных за сопровождение и/или усовершенствование ПО. В зависимости от сущности вносимых изменений на этом этапе могут возникать практически любые ошибки, аналогичные ранее перечисленным ошибкам на предыдущих этапах.
Все ошибки, которые возникают в программах, принято подразделять на следующие классы:
- логические и функциональные ошибки;
- ошибки вычислений и времени выполнения;
- ошибки вводавывода и манипулирования данными;
- ошибки интерфейсов;
- ошибки объема данных и др.
Логические ошибки являются причиной нарушения логики алгоритма, внутренней несогласованности переменных и операторов, а также правил программирования. Функциональные ошибки — следствие неправильно определенных функций, нарушения порядка их применения или отсутствия полноты их реализации и т.д.
Ошибки вычислений возникают по причине неточности исходных данных и реализованных формул, погрешностей методов, неправильного применения операций вычислений или операндов. Ошибки времени выполнения связаны с необеспечением требуемой скорости обработки запросов или времени восстановления программы.
Ошибки ввода-вывода и манипулирования данными являются следствием некачественной подготовки данных для выполнения программы, сбоев при занесении их в базы данных или при выборке из нее.
Ошибки интерфейса относятся к ошибкам взаимосвязи отдельных элементов друг с другом, что проявляется при передаче данных между ними, а также при взаимодействии со средой функционирования.
Ошибки объема относятся к данным и являются следствием того, что реализованные методы доступа и размеры баз данных не удовлетворяют реальным объемам информации системы или интенсивности их обработки.
Приведенные основные классы ошибок свойственны разным типам компонентов ПО и проявляются они в программах по разному. Так, при работе с БД возникают ошибки представления и манипулирования данными, логические ошибки в задании прикладных процедур обработки данных и др. В программах вычислительного характера преобладают ошибки вычислений, а в программах управления и обработки — логические и функциональные ошибки. В ПО, которое состоит из множества разноплановых программ, реализующих разные функции, могут содержаться ошибки разных типов. Ошибки интерфейсов и нарушение объема характерны для любого типа систем.
Анализ типов ошибок в программах является необходимым условием создания планов тестирования и методов тестирования для обеспечения правильности ПО.
На современном этапе развития средств поддержки разработки ПО (CASE-технологии, объектно-ориентированные методы и средства проектирования моделей и программ) проводится такое проектирование, при котором ПО защищается от наиболее типичных ошибок и тем самым предотвращается появление программных дефектов.
Связь ошибки с отказом. Наличие ошибки в программе, как правило, приводит к отказу ПО при его функционировании. Для анализа причинно-следственных связей «ошибкаотказ» выполняются следующие действия:
- идентификация изъянов в технологиях проектирования и программирования;
- взаимосвязь изъянов процесса проектирования и допускаемых человеком ошибок;
- классификация отказов, изъянов и возможных ошибок, а также дефектов на каждом этапе разработки;
- сопоставление ошибок человека, допускаемых на определенном процессе разработки, и дефектов в объекте, как следствий ошибок спецификации проекта, моделей программ;
- проверка и защита от ошибок на всех этапах ЖЦ, а также обнаружение дефектов на каждом этапе разработки;
- сопоставление дефектов и отказов в ПО для разработки системы взаимосвязей и методики локализации, сбора и анализа информации об отказах и дефектах;
- разработка подходов к процессам документирования и испытания ПО.
Конечная цель причинно-следственных связей «ошибка-отказ» заключается в определении методов и средств тестирования и обнаружения ошибок определенных классов, а также критериев завершения тестирования на множестве наборов данных; в определении путей совершенствования организации процесса разработки, тестирования и сопровождения ПО.
Приведем следующую классификацию типов отказов:
- аппаратный, при котором общесистемное ПО не работоспособно;
- информационный, вызванный ошибками во входных данных и передаче данных по каналам связи, а также при сбое устройств ввода (следствие аппаратных отказов);
- эргономический, вызванный ошибками оператора при его взаимодействии с машиной (этот отказ — вторичный отказ, может привести к информационному или функциональному отказам);
- программный, при наличии ошибок в компонентах и др.
Некоторые ошибки могут быть следствием недоработок при определении требований, проекта, генерации выходного кода или документации. С другой стороны, они порождаются в процессе разработки программы или при разработке интерфейсов отдельных элементов программы (нарушение порядка параметров, меньше или больше параметров и т.п.).
Источники ошибок. Ошибки могут быть порождены в процессе разработки проекта, компонентов, кода и документации. Как правило, они обнаруживаются при выполнении или сопровождении программного обеспечения в самых неожиданных и разных ее точках.
Некоторые ошибки в программе могут быть следствием недоработок при определении требований, проекта, генерации кода или документации. С другой стороны, ошибки порождаются в процессе разработки программы или интерфейсов ее элементов (например, при нарушении порядка задания параметров связи — меньше или больше, чем требуется и т.п.).
Причиной появления ошибок — непонимание требований заказчика; неточная спецификация требований в документах проекта и др. Это приводит к тому, что реализуются некоторые функции системы, которые будут работать не так, как предлагает заказчик. В связи с этим проводится совместное обсуждение заказчиком и разработчиком некоторых деталей требований для их уточнения.
Команда разработчиков системы может также изменить синтаксис и семантику описания системы. Однако некоторые ошибки могут быть не обнаружены (например, неправильно заданы индексы или значения переменных этих операторов).