Калашников, Е. И. Процесс тестирования программного обеспечения, типы и методы тестирования / Е. И. Калашников, М. А. Иванова. — Текст : непосредственный // Молодой ученый. — 2020. — № 50 (340). — С. 27-31. — URL: https://moluch.ru/archive/340/76390/ (дата обращения: 18.06.2023).
Тестирование программного обеспечения является наиболее важной фазой жизненного цикла разработки программного обеспечения. Тестируемое программное обеспечение проходит различные фазы, которые, согласно исследованию, являются тестовым анализом: планирование тестирования; подготовка тестового примера данных, среды; выполнение теста; регистрация ошибок; отслеживание и закрытие;
В прошлом было проведено много исследований для оптимизации всего процесса тестирования с целью улучшения качества программного обеспечения за минимальное время. После оценки всех доступных процессов тестирования было обнаружено, что для разных типов приложений используются разные модели разработки, и для тестирования используются разные методы тестирования.
Открытый урок СПО: Тестирование ПО
На основе исследований, проведенных в ходе изучения этой статьи, было проанализировано, что каждая компания модифицирует свой процесс тестирования в соответствии с потребностями и выполняет тестирование в зависимости от критичности приложений. Наиболее важные компоненты каждого приложения должны быть тщательно протестированы, чтобы убедиться, что их функции, производительность и функции безопасности работают должным образом. В этой статье говорится об обеспечении качества всех типов программных приложений путем выполнения определенных типов методов тестирования и оптимизированных процессов тестирования программного обеспечения. В соответствии с исследованиями и проведенными исследованиями типы тестирования могут быть разделены на три основных метода тестирования: функциональное тестирование, тестирование производительности и безопасности, а также основной процесс тестирования программного обеспечения, называемый анализом, подготовкой, выполнением и закрытием.
Ключевые слова: функциональное тестирование, тестирование производительности и безопасности (FPS), анализ, планирование и подготовка, выполнение и закрытие (APEC), методы тестирования программного обеспечения, жизненный цикл тестирования программного обеспечения (STLC), жизненный цикл разработки программного обеспечения (SDLC).
Software testing is the most critical phase of the Software Development Life Cycle. Software under test goes through various phases, which as per the study are test analysis: test planning, test case data, environment preparation, test execution, bug logging and tracking and closure.
There is lot of research which has been done in past to optimize overall testing process with intent of improving quality of software in a minimum amount of time. After evaluating all available testing processes, it has been found that different development models are used for different types of applications and different testing techniques are performed to test the same. Based on the research during the study of this paper, it has been analyzed that each company modifies their testing process as per the needs and performs testing based on the criticality of the applications. The most critical components of each application have to be tested thoroughly to ensure their functional, performance and security features are behaving as expected. This paper talks about ensuring the quality of all types of software applications by performing certain types of testing techniques and optimized software testing processes. As per the study and research done testing types can be categorized under three major testing techniques which are Functional, Performance and Security Testing and major software testing process called as Analysis, Preparation and Execution and closure
Black-box vs White-box testing. Методологии тестирования | Курс тестирование ПО — Урок 8 | QA Labs
Keywords: Functional, Performance and Security Testing (FPS), Analysis, Planning and Preparation, Execution and Closure (APEC), Software Testing Techniques, Software Testing Life Cycle (STLC), Software Development Life Cycle (SDLC).
Эта статья состоит из двух разделов. В первом разделе описывается оптимизированный процесс тестирования, в котором рассматриваются все этапы жизненного цикла тестирования, а во втором разделе рассматриваются типы тестирования.
Существует множество доступных типов тестирования, таких как тестирование «черного ящика», тестирование «белого ящика», тестирование на основе состояния, тестирование безопасности, тестирование на приемлемость, приемочное тестирование, системное тестирование, альфа- и бета-тестирование, а также тестирование на основе конфигурации, проверка и валидация.
Основываясь на проведенных исследованиях и исследованиях, эта статья классифицировала их всех по трем типам тестирования высокого уровня, а именно: Функциональность, Производительность и Безопасность (FPS). Последний раздел посвящен заключению, которое показывает актуальность нашего оптимизированного процесса тестирования программного обеспечения и FPS как основа для методов тестирования.
Оптимизированный процесс тестирования программного обеспечения
Этапы STLC связаны с обнаружением и исправлением любой ошибки с использованием различных методов тестирования программного обеспечения.
В этом разделе представлены обязательные этапы жизненного цикла тестирования, без которых жизненный цикл программного обеспечения не будет выполнен эффективно. Тестирование в основном дает критику или сравнение, которое определяет поведение системы в отношении ее спецификаций, механизмов, принципов, характеристик и соответствующих стандартов. Процесс тестирования программного обеспечения может быть настроен в соответствии с потребностями клиента или проекта. Процесс оптимизации, который можно использовать при тестировании программного обеспечения, — это анализ, планирование и подготовка, выполнение и закрытие. Процесс программного обеспечения обеспечивает поток системы и повышает гарантию продукта, который будет произведен.
Этап анализа тестирования
Первый этап, который является этапом анализа, является основным этапом процесса тестирования программного обеспечения. Эта фаза включает анализ функциональных и нефункциональных требований, например, бизнес-требования, функциональная документация и документ технической спецификации и т. д.
Сбор требований должен быть согласован с клиентами, чтобы идентифицировать фактические и ожидаемые результаты тестирования, которые в основном являются нефункциональными требованиями, такими как: удобство использования, масштабируемость, тестируемость, производительность и безопасность.
Все требования, которые не могут быть проверены из-за ограничений системы и среды тестирования, должны быть сообщены бизнес-команде.
На этом этапе команда тестирования рассматривает и анализирует требования и определяет тесты, которые должны быть выполнены, и устанавливает приоритеты для тестирования — членов команды.
Требования к среде тестирования включают требования к аппаратному и программному обеспечению, в соответствии с которыми необходимо тестировать необходимое программное обеспечение, и параллельно разработчики программного обеспечения начинают с планирования и разработки.
Этап планирования и подготовки теста
Этап подготовки теста включает подготовку плана тестирования, тестовый набор, данные теста и подготовку среды тестирования.
План тестирования является первым документом, который должен быть подготовлен, в котором описываются объем, цели, характеристики, подлежащие тестированию, функции, которые не должны тестироваться, типы тестирования, которые должны быть выполнены, роли и обязанности группы тестирования, критерии входа и выхода и предположения [1, с. 122].
Одновременно команды тестирования начинают готовить тестовые наборы и тестовые данные. Тестовый пример — это документ, в котором описаны шаги, необходимые для тестирования любой функциональности с ожидаемым и фактическим результатом. Если фактический результат не совпадает с ожидаемым, открывается ошибка. Для каждого требования подготавливаются положительные и отрицательные тестовые примеры, что обеспечивается матрицей прослеживаемости требований (RTM). RTM — это документ, который сопоставляет требования с тестовыми примерами, чтобы гарантировать, что тестирование выполнено на 100 %
Все действительные и недействительные наборы тестовых данных должны быть подготовлены для каждого тестового случая и подготовлен документ с тестовыми данными. Тестовые данные также генерируются на основе некоторых алгоритмов и инструментов. Подготовка тестового набора включает в себя различные этапы, которые начинаются с создания тестового набора, выбора тестового набора, оценки и определения приоритетов тестового набора [7, с. 57].
Эрик Д. Свайн предложил метод генерации тестовых случаев с использованием соответствующих диаграмм последовательности, а также определяет ограничения для определенных артефактов. В то же время методы генерации тестовых наборов полезны для выявления синхронизации и зависимости вариантов использования и сообщений, взаимодействия объектов и ошибок работы [8, с. 87].
Подготовка тестовой среды является одним из наиболее важных этапов, которые обычно готовятся отдельными средами обработки команды. После завершения части кода код проверяется инструментом управления конфигурацией, а затем готовится тестовая сборка, где тестировщики должны начать выполнение теста.
Этап выполнения теста
На этом этапе тестеры выполняют программное обеспечение в соответствии с контрольными примерами. Везде, где фактические и ожидаемые результаты не совпадают, тестировщик открывает ошибки и назначает их разработчикам.
Закрытие теста — это важный этап, который включает в себя все отчеты о тестировании, гарантирующие, что вся система, интеграция, приемочное тестирование пользователя пройдены, и принято решение о том, все ли требования проверены, и нет критической ошибки, ожидающей исправления ИЛИ проверки. Просмотр всех тестовых артефактов выполняется менеджером. Как только все артефакты рассмотрены и утверждены, выполняется выпуск программного обеспечения. Проводится дальнейший анализ первопричин, чтобы провести мозговой штурм по поводу того, что прошло хорошо, что не удалось, и областей улучшения. Существуют различные инструменты и методы анализа первопричин, по которым в прошлом было проведено много исследований.
Виды тестирования программного обеспечения
Существуют различные методы тестирования программного обеспечения согласно исследованию и изучению, такие как черный ящик, белый ящик, серый ящик, регрессия, надежность, удобство использования, производительность, модуль, система, интеграция, безопасность, дым, здравомыслие и объектно-ориентированное тестирование и т. д.
Невозможно выполнить все виды тестирования на программном обеспечении, поскольку для тестирования всегда выделяется определенное количество времени.
Функциональное тестирование очень распространено, и в прошлом было проведено немало исследований, поэтому только в редких случаях происходит сбой сайта из-за отсутствия функционального тестирования.
Эта раздел статьи будет посвящена основным методам тестирования, таким как функциональное [F], производительность [P] и тестирование безопасности [S]. Правильное сочетание тестирования должно быть включено со всех заголовков F, P и S.
Функциональность — это прежде всего аспект тестирования программного обеспечения, обеспечивающий качество программного обеспечения.
Проверка и валидация выполняются с использованием статического и динамического тестирования соответственно. Статическое тестирование включает в себя все виды проверок, проверок и прохождений. Динамическое тестирование или фактическая проверка включает все функциональные и нефункциональные типы тестирования.
Основным фактором качества в программном обеспечении является соответствие его требуемым функциональным возможностям и поведению. Функциональная часть программного обеспечения включает внешнее поведение, которое в основном определяет все требования пользователя. Разработка программного обеспечения высокого уровня производится таким образом, чтобы заказчик был удовлетворен на ранней стадии проектирования и разработки.
Существуют различные типы функционального тестирования, которые могут выполняться на различных уровнях тестирования, то есть модульное тестирование, интеграционное тестирование (тестирование сверху вниз и тестирование снизу вверх) и тестирование системы.
Существует много тестов, проводимых на различных уровнях тестирования, таких как тестирование черного ящика, тестирование белого ящика, тестирование серого ящика, регрессионное тестирование, нечеткое тестирование, тестирование варианта использования, предварительное тестирование, тестирование на дым., тестирование работоспособности, приемочное тестирование, альфа-тестирование, бета-тестирование и т. д.
Основные типы функционального тестирования кратко описаны в таблице 1:
Описание типов функционального тестирования
Тип тестирования
Описание
Источник: moluch.ru
34 Основные принципы тестирования программ. Заповеди по тестированию, предложенные г. Майерсом. Методы тестирования, два подхода к тестированию.
Тестирование ПС — это процесс выполнения его программ на некотором наборе данных, для которого заранее известен результат применения или известны правила поведения этих программ. Указанный набор данных называется тестовым или просто тестом. Таким образом, отладку можно представить в виде многократного повторения трех процессов: тестирования, в результате которого может быть констатировано наличие в ПС ошибки, поиска места ошибки в программах и документации ПС и редактирования программ и документации с целью устранения обнаруженной ошибки.
Тестирование – процесс многократного повторения программы с целью обнаружения ошибок. Тестирование – составная часть отладки.
Заповеди, предложенные Майерсом, по тестированию ПС.
- Заповедь 1. Считайте тестирование ключевой задачей разработки ПС, поручайте его самым квалифицированным и одаренным программистам; нежелательно тестировать свою собственную программу;
- Заповедь 2. Хорош тот тест, для которого высока вероятность обнаружить ошибку, а не тот, который демонстрирует правильную работу программы;
- Заповедь 3. Готовьте тесты как для правильных, так и для неправильных данных;
- Заповедь 4. Документируйте пропуск тестов через компьютер; детально изучайте результаты каждого теста; избегайте тестов, пропуск которых нельзя повторить;
- Заповедь 5. Каждый модуль подключайте к программе только один раз; никогда не изменяйте программу, чтобы облегчить ее тестирование;
- Заповедь 6. Пропускайте заново все тесты, связанные с проверкой работы какой-либо программы ПС или ее взаимодействия с другими программами, если в нее были внесены изменения (например, в результате устранения ошибки).
Существуют следующие методы тестирования ПС:
- Статическое тестирование – ручная проверка программы за столом.
- Детерминированное тестирование – при различных комбинациях исходных данных.
- Стохастическое – исходные данные выбираются произвольно, на выходе определяется качественное совпадение результатов или примерная оценка.
Имеется два подхода к тестированию:
- Структурное тестирование – метод «белого ящика», тестируется логика программы, внутренняя структура программы.
- Функциональное тестирование – метод «черного ящика»- тестируется спецификация, т.е. вход/выход без учета знаний о ее структуре.
Структурное тестирование При данном подходе считается, что текст программы виден (белый ящик). Тестируются блоки ветвлений, циклы и т.д. Существует несколько типов структурного тестирования:
- покрытие операторов;
- покрытие решений;
- покрытие решений / условий;
- комбинаторное покрытие условий;
- тестирование циклов.
Функциональное тестирование При данном подходе считается, что текст программы не виден, и программа рассматривается как черный ящик, т.е. известны входные и выходные условия, а также общая схема работы. Программа проверятся по ее спецификациям. Существуют несколько видов функционального тестирования:
- эквивалентные классы;
- анализ граничных значений;
- тестирование на предельных нагрузках;
- тестирование на предельных объемах;
- тестирование защиты;
- эксплуатация системы самим разработчиком (если возможно);
- опытная эксплуатация.
35 Тестирование модулей: тестирование путей, структур управления, ветвлений, специальных значений (примеры).
- Тестирование путей — самая подробная проверка — должны быть выялены всевозможные пути прохождения по модулю;
рисунок
- Тестирование структуры управления;
При тестировании управляющих структур считается, что одного прохода по циклу достаточно.
- Тестирование ветвлений — анализируются точки ветвления управляющего графа;
- Тестирование специальных значений — деление на ноль, потеря значимости и так далее;
36 Автономная отладка ПС. Комплексная отладка ПС. В нашей стране различаются два основных вида отладки (включая тестирование): автономную и комплексную отладку ПС. Автономная отладка ПС означает последовательное раздельное тестирование различных частей программ, входящих в ПС, с поиском и исправлением в них фиксируемых при тестировании ошибок. Она фактически включает отладку каждого программного модуля и отладку сопряжения модулей. Автономная отладка ПС — последовательное раздельное тестирование различных частей программ с поиском и исправлением в них фиксируемых при тестировании ошибок. Комплексная отладка — тестирование ПС в целом с поиском и исправлением фиксируемых при тестировании ошибок во всех документах. При автономной отладке тестируется всегда некоторая программа (тестируемая программа), построенная специально для тестирования отлаживаемого модуля. В процессе автономной отладки ПС производится наращивание тестируемой программы отлаженными модулями (интеграция программы). При восходящем тестировании окружение содержит только один отладочный модуль, головной в тестируемой программе — ведущий (или драйвер). Ведущий отладочный модуль подготавливает информационную среду для тестирования отлаживаемого модуля, осуществляет обращение к отлаживаемому модулю и выдает необходимые сообщения. При нисходящем тестировании окружение в качестве отладочных содержит отладочные имитаторы (заглушки) некоторых еще не отлаженных модулей. Некоторые из этих имитаторов при отладке одного модуля могут изменяться для разных тестов. На практике в окружении отлаживаемого модуля могут содержаться отладочные модули обоих типов, если используется смешанная стратегия тестирования. Достоинства восходящего тестирования:
- Простота подготовки тестов;
- Возможность полной реализации плана тестирования модуля.
Недостатки восходящего тестирования:
- Тестовые данные готовятся, как правило, не в той форме, которая рассчитана на пользователя;
- Большой объем отладочного программирования;
- Необходимость специального тестирования сопряжения модулей.
Достоинства нисходящего тестирования:
- Большинство тестов готовится в форме, рассчитанной на пользователя;
- Во многих случаях относительно небольшой объем отладочного программирования;
- Отпадает необходимость тестирования сопряжения модулей.
Недостатком нисходящего тестирования является то, что тестовое состояние информационной среды перед обращением к отлаживаемому модулю готовится косвенно — оно является результатом применения уже отлаженных модулей к тестовым данным или данным, выдаваемым имитаторами. Прежде всего, необходимо организовать отладку программы таким образом, чтобы как можно раньше были отлажены модули, осуществляющие ввод данных. Пока модули, осуществляющие ввод данных, не отлажены, тестовые данные поставляются некоторыми имитаторами: они либо включаются в имитатор как его часть, либо вводятся этим имитатором. При нисходящем тестировании некоторые состояния информационной среды, при которых требуется тестировать отлаживаемый модуль, могут не возникать при выполнении отлаживаемой программы ни при каких входных данных. Чаще же пользуются модифицированным вариантом нисходящего тестирования, при котором отлаживаемые модули перед их интеграцией предварительно тестируются отдельно. Однако, представляется более целесообразной другая модификация нисходящего тестирования: после завершения нисходящего тестирования отлаживаемого модуля для достижимых тестовых состояний информационной среды следует его отдельно протестировать для остальных требуемых состояний информационной среды. Часто применяют также комбинацию восходящего и нисходящего тестирования, которую называют методом сандвича. Сущность этого метода заключается в одновременном осуществлении как восходящего, так и нисходящего тестирования, пока эти два процесса тестирования не встретятся на каком-либо модуле где-то в середине структуры отлаживаемой программы. Весьма важным при автономной отладке является тестирование сопряжения модулей. При нисходящем тестировании тестирование сопряжения осуществляется попутно каждым пропускаемым тестом, что считают достоинством нисходящего тестирования. При восходящем тестировании обращение к отлаживаемому модулю производится не из модулей отлаживаемой программы, а из ведущего отладочного модуля. Автономное тестирование модуля целесообразно осуществлять в четыре последовательно выполняемых шага.
- Шаг 1. На основании спецификации отлаживаемого модуля подготовьте тесты для каждой возможности и каждой ситуации, для каждой границы областей допустимых значений всех входных данных, для каждой области изменения данных, для каждой области недопустимых значений всех входных данных и каждого недопустимого условия.
- Шаг 2. Проверьте текст модуля, чтобы убедиться, что каждое направление любого разветвления будет пройдено хотя бы на одном тесте. Добавьте недостающие тесты.
- Шаг 3. Проверьте текст модуля, чтобы убедиться, что для каждого цикла существуют тесты, обеспечивающие, по крайней мере, три следующие ситуации: тело цикла не выполняется ни разу, тело цикла выполняется один раз и тело цикла выполняется максимальное число раз. Добавьте недостающие тесты.
- Шаг 4. Проверьте текст модуля, чтобы убедиться, что существуют тесты, проверяющие чувствительность к отдельным особым значениям входных данных. Добавьте недостающие тесты.
Комплексная отладка означает тестирование ПС в целом с поиском и исправлением фиксируемых при тестировании ошибок во всех документах (включая тексты программ ПС), относящихся к ПС в целом. К таким документам относятся определение требований к ПС, спецификация качества ПС, функциональная спецификация ПС, описание архитектуры ПС и тексты программ ПС. Тестирование при комплексной отладке — применение ПС к конкретным данным, которые могут возникнуть у пользователя, но, возможно, в моделируемой (а не в реальной) среде. Тестирование архитектуры ПС. Целью тестирования является поиск несоответствия между описанием архитектуры и совокупностью программ ПС. К моменту начала тестирования архитектуры ПС должна быть уже закончена автономная отладка каждой подсистемы. Тестирование внешних функций. Целью тестирования является поиск расхождений между функциональной спецификацией и совокупностью программ ПС. Несмотря на то, что все эти программы автономно уже отлажены, указанные расхождения могут быть. Тестирование качества ПС. Целью тестирования является поиск нарушений требований качества, сформулированных в спецификации качества ПС. Завершенность ПС проверяется уже при тестировании внешних функций. Тестирование документации по применению ПС. Целью тестирования является поиск несогласованности документации по применению и совокупностью программ ПС, а также выявление неудобств, возникающих при применении ПС. Этот этап непосредственно предшествует подключению пользователя к завершению разработки ПС (тестированию определения требований к ПС и аттестации ПС). Тестирование определения требований к ПС. Целью тестирования является выяснение, в какой мере ПС не соответствует предъявленному определению требований к нему. Особенность этого вида тестирования заключается в том, что его осуществляет организация-покупатель или организация-пользователь. Обычно производится с помощью контрольных задач — типовых задач, для которых известен результат решения. 37 Необходимость коллективной разработки ПО. Метод бригады главного программиста. Состав бригады. Обязанности главного программиста. Если
- Некоторые задачи очень сложны , чтобы справиться с ними нужно решить много подзадач. К моменту формирования исходной задачи решение этих подзадач не найдено. Человек последовательно занимающийся этими задачами не закончит их в срок.
- Некоторые задачи очень объемные Прогнозируемые задачи можно закончить раньше если работать параллельно
- Некоторые задачи требуют кооперации программистов, обладающих специальными знаниями
Задача может потребовать коллективного решения. Миллс «Бригада главного программирования» Создается группа из 5 10 человек Бригада состоит и з главного програмера , помошника главного програмера , секретарь (библиотекарь) , программисты исполнители. Идея — работает как один программист высокой квалификации. Главный програмер несет 100% ответственность за проектирование ПС. Распределяет работу, принимает решения. Отвечает за успех .Пишет важные процедуры и функции, определенные спецификацией для остальных модулей,ю объединяет результаты в единое целое. Руководство персоналом, соблюдение условий контракта, регулирование отношений с заказчиком .Решает когда и сколько программистов может понадобиться.
Источник: studfile.net
Home
Меня зовут Георгий Костуров, я лид фронта в одной из команд СберМаркета. Хочу рассказать про виды тестов и рассмотреть несколько подходов к тестированию. В основном здесь примеры из frontend, но идеи подойдут и для backend. В статье нет конкретных примеров кода (хотя присутствуют ссылки на материалы, где они есть), но изложены идеи и общие правила написания тестов.
Какие бывают тесты
Существуют различные классификации видов тестирования: по объекту, знанию внутреннего строения, степени автоматизации, степени изоляции и т. д.
Я расскажу о видах тестирования по степени изоляции, то есть объему того, что именно тестируем — отдельную функцию или весь объект в целом. Их существует три вида: юнит-тестирование, интеграционное и end-to-end.
Четкого определения, какие тесты к какому виду относятся, не существует. Разные школы тестирования один и тот же тест могут отнести к юнит- или интеграционному. Я расскажу про свой опыт и подход к этой классификации.
Юнит-тестирование
Юнит-тестирование представляет собой полностью изолированные тесты, которые покрывают классы или отдельные функции. С утилитами и чистыми функциями всё просто: подаем тестовые данные на вход, получаем результат и сравниваем с ожиданиями.
А как поступать с компонентами, у которых есть зависимости в виде других компонентов или даже сторов и внешнего API? Надо мокать!
Мок (mock) — объект-имитация. Он повторяет нужный компонент с необходимой точностью и реализует его интерфейс или API. Используется только в тестовом окружении. Например, для тестов бэкенда можно замокать репозиторий, чтобы он записывал и читал данные из оперативной памяти, в то время как реальный репозиторий работает с БД.
Стаб (stub) — объект-заглушка с интерфейсом связанных компонентов или API, но без логики. Например, объект, метод которого возвращает один и тот же результат на его вызов. Или с предустановленным набором параметров: при единице на входе возвращает один объект, при двойке — другой.
Обычно стабы используют для заглушек API. Например, запрос GET api/user/1 будет возвращать одного и того же юзера без необходимости запускать реальный бэкенд.
Важная особенность: считывать данные можно и из моков, и из стабов. А вот записывать — только в мок. В большинстве случаев стабы предпочтительнее, поскольку их логика не меняется и писать их быстрее, чем моки.
Как писать юнит-тесты
Шаг 1. Заменяем моками и стабами всё, что не относится к тестируемому компоненту. Это можно сделать через dependency injection или используя инструменты типа jest.mock.
Шаг 2. Проверяем дефолтный сценарий и граничные условия, причем как положительные, так и отрицательные случаи с ошибкой.
Не стоит:
- тестировать тривиальные случаи, например геттеры и сеттеры, которые приводит в пример Роберт Мартин в своей статье;
- гнаться за процентом покрытия кода — после достижения 70–80% покрытия сложно написать полезный тест.
Юнит тестирует публичные методы класса/компонента. Важное уточнение: тестировать надо только открытый интерфейс, поскольку внутренности в дальнейшем могут быть отрефакторены. Кроме того, если завязываться на внутреннее устройство, легко погрязнуть в тавтологических тестах, которые говорят только то, что код работает ровно так, как написан.
Если появляется желание протестировать внутреннюю часть компонента, то, скорее всего, тестирование пошло не по плану и компонент нужно декомпозировать. Например, сложную логику вытащить в отдельную утилиту и тестировать её отдельно, а в тестах всего компонента не уделять ей внимания.
Если в компоненте есть несколько сложных методов, которые хочется протестировать, то их точно надо выносить, поскольку тут в игру вступает комбинаторика. И если у одного метода 5 возможных исходов и у второго тоже, то, если мы оставим их в компоненте, для них придётся написать 25 тестов вместо 10. В качестве примера можно рассмотреть кнопку, у которой можно задать один из пяти цветов и один из пяти размеров.
Интеграционное тестирование
В интеграционных тестах мы проверяем работу нескольких компонентов или классов в связке. Моками и стабами в нём закрывают только межсервисное взаимодействие, например обращение по API к бэкенду или между микросервисами. На фронте удобно мокать запросы API, используя MSW.
Чётких правил здесь нет, они исходят из задачи компонента, но есть несколько советов. Например, не стоит тестировать логику работы внешних библиотек (реакта и его стейта, баз данных) и прочих не зависящих от нас вещей. Кроме того, в этих тестах не стоит смотреть на визуальное отображение, нас интересует, чтобы компонент работал.
Остаётся тестировать то, что часто ломается: бизнес-логику, модель данных и пограничные ситуации. Здесь в первую очередь ориентируемся на пользовательские сценарии.
Например, есть страница авторизации. Пытаемся угадать действия пользователя: вводим логин и пароль, нажимаем кнопку «Войти» и смотрим, что в мок бэкенда пришёл запрос с нужными параметрами. В следующем тесте проверяем, появляется ли ошибка, если пользователь ввёл только логин.
Есть правило: один тест — один сценарий. Если есть общие части у тестов, их выносят в отдельную функцию и выполняют в beforeEach, либо просто руками там, где она нужна. Это хорошо согласуется с принципом единой ответственности.
End-to-end (e2e), или Сквозное тестирование
End-to-end-тестирование эмулирует действия пользователей в среде, идентичной проду. Если речь идёт про клиент-серверное веб-приложение, то для его тестирования нужно поднимать полноценные фронт и бэк и писать бота, повторяющего поведение пользователя. Он будет заходить на сайт, нажимать кнопки, пытаться авторизоваться и т. д.
e2e помогает избежать регрессионного тестирования, автоматизировать работу тестировщиков и отловить баги, которые не смогли отловить нижние уровни тестов.
Как выбрать тесты для кода
С видами тестов разобрались, теперь нужно соотнести их друг с другом. На данный момент популярна концепция пирамиды тестирования, получившая мировую известность в 2009 году после публикации книги Майка Коэна «Succeeding with Agile». Эта концепция подразумевает, что больше всего должно быть юнит-тестов, меньше интеграционных и совсем мало e2e. Подробно об этом соотношении автор рассказывает в статье The Forgotten Layer of the Test Automation Pyramid.
Так выглядит примерное соотношение тестов согласно пирамиде тестирования
В пирамиде тестам e2e уделено меньше всего внимания. Это кажется нелогичным, ведь такие тесты эмулируют действия пользователя и, казалось бы, их нужно как можно больше.
На самом деле всё не так просто. Тесты не только ищут ошибки, но и ускоряют разработку: упрощают рефакторинг кода, находят, где сломалась логика, и автоматически проверяют код. Но чтобы обеспечить экономию времени, тесты должны быть быстрыми.
Эмуляция в e2e требует десятки секунд на один тест. А тысяча тестов займёт 3 часа, что сильно увеличивает lead time. Особенно если будет обнаружена ошибка: её исправят и тесты придётся начинать снова.
У е2е есть ещё одна проблема: после обнаружения самой ошибки непонятно, где именно она произошла. Например, не работает авторизация. А где эта проблема? На фронте, на бэке, в каком модуле? Локализация проблемы отнимет дополнительное время.
Подробнее об этом рассказано в статье инженеров «Гугла» Just Say No to More End-to-End Tests.
Сузить область и изолированно воспроизвести ошибку позволяют тесты более низкого уровня. Они работают быстрее и менее раздуты, что помогает при отладке вручную.
Но есть и обратная сторона. Чем ниже к основанию пирамиды, тем больше тесты оторваны от реальных действий пользователя. В итоге иногда получается так, что все юнит-тесты успешно пройдены, но программа всё равно не работает:
Щеколда сама по себе работает, и дверь сама тоже работает — это видно из «unit-тестов» обоих изолированных компонентов. Но их связка, то есть интеграционный тест, показывает, что система в целом сломана
Что учитывать при выборе соотношения тестов
Тестировать всё не имеет смысла, это очень затратно:
- каждый компонент нужно мокать;
- если меняется код, то придется менять и тесты;
- при изменении класса нужно поменять моки этого класса;
- сам код теста тоже надо проверить на ошибки.
В конечном итоге мы приходим к тому, что количество тестов зависит от бюджета и этапа разработки продукта.
Бюджет. Сколько денег бизнесу принесет сэкономленное на тестах время? А сколько будет стоить ошибка на проде? Если первое больше второго, тестов можно делать меньше. Если наоборот, лучше соблюдать пирамиду.
Этап разработки продукта. На старте, когда компания пишет MVP, а концепция регулярно меняется, покрывать всё тестами бессмысленно и даже вредно. А в большом проекте невозможно расширить функционал без риска сломать уже существующий. Поэтому без тестов разработка просто встанет.
В зависимости от приоритетов можно выделить несколько основных стратегий:
- Качество. Используем пирамиду тестирования. Пишем юнит-тесты на компоненты и интеграционные на группы компонентов, не забываем про e2e. Многоуровневое исчерпывающее тестирование потребует много времени и ресурсов, но поймает критичные дефекты.
- Скорость. Пишем e2e на основные пользовательские сценарии. Так мы заблаговременно обнаружим критические дефекты, а остальное починим, если обнаружим поломку. И в итоге быстро поставляем функциональность.
- Баланс. Покрываем тестами все компоненты, но мокаем только API и то, что связано с динамически изменяющимися параметрами. Например, получение текущей даты. Каждый компонент вышележащего уровня тестируем исходя из того, что компоненты нижележащего уровня уже протестированы и не требуют дополнительной проверки. А значит, их можно безопасно использовать, игнорируя их внутреннюю цикломатическую сложность. Требует меньше ресурсов, но занимает чуть больше времени.
Логичным кажется идти путём баланса. Но возникает вопрос: как локализовать баг, если покраснело сразу несколько тестов? На самом деле, просто: настроить всё так, чтобы сначала запускались тесты компонентов низких уровней и только потом — уровней выше.
Вся эта история противоречит пирамиде тестирования, ведь интеграционных тестов у нас получается больше, чем юнит-. Но это не плохо — это просто другой подход, который называется трофеем тестирования.
Альтернатива пирамиде: трофей тестирования
Идею трофея тестирования предложил Кент Дотс несколько лет назад. Тесты в этом подходе представлены в виде кубка и разделены на четыре уровня:
- статическое тестирование,
- юнит-тесты,
- интеграционные тесты,
- тесты e2e.
В подходе «трофея тестирования» был добавлен ещё один тип теста — статическое тестирование. Это всевозможные линтеры, статические проверки типов и прочие инструменты, зачастую работающие в фоновом режиме. Они отлавливают ошибки во время написания кода, еще до запуска тестов. На самом деле, очень полезная вещь, особенно во время рефакторинга.
В трофее больше всего интеграционных тестов, чуть поменьше статических, а юнит- и сквозных очень мало. Как раз такой подход позволяет добиться баланса: тратить на тесты меньше времени и денег, но не пропускать критичные ошибки.
Подробнее о трофее Кент Дотс, его автор, рассказывает в своей статье Static vs Unit vs Integration vs e2e Testing for Frontend Apps. Рекомендую её прочитать — в ней много примеров использования тестов в связке с React.
Ключевые правила при составлении тестов
- В первую очередь проверяем дефолтный сценарий и граничные условия. Нужно проверять как положительные, так и отрицательные случаи.
- Нужно тестировать только внешнее поведение класса/компонента, не вдаваясь в его устройство. Иначе получится тавтологический тест.
- Если возникает желание протестировать логику внутри компонента, то её следует вынести в отдельную утилиту. Так вы предотвратите рост цикломатической сложности тестирования всего компонента.
- Не стоит тестировать тривиальные случаи и гнаться за процентом покрытия кода.
- В первую очередь необходимо тестировать бизнес-логику и пользовательские сценарии использования. Если говорить про фронт, то задача тестов остаётся той же: в первую очередь тестируем логику, а не визуальное отображение.
- Тесты должны быть атомарными. Не стоит в один тест запихивать несколько сценариев.
- Для соблюдения баланса лучше всего писать юнит-тесты на общие утилиты и компоненты. А интеграционные — на целые страницы, формы, модалки и прочие самостоятельные вещи. При этом считаем, что все нижестоящие компоненты уже протестированы и работают.
Как видите, в тестировании нет однозначных решений. Я поделился своим видением, а вы делитесь тем, что применяете в своих проектах, и задавайте вопросы. Если материал понравится, напишу продолжение с конкретными примерами/ошибками из личного опыта.
Источник: www.software-testing.ru